Completed
Push — symfony3-fqcn-sylius-2 ( 026c63...c92ad2 )
by Kamil
31:21 queued 13:20
created

CreateSimpleProductPage::specifySlugIn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
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($price)
64
    {
65
        $this->getDocument()->fillField('Price', $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 specifyPriceForChannelAndCurrency($price, ChannelInterface $channel, CurrencyInterface $currency)
169
    {
170
        $calculatorElement = $this->getElement('calculator');
171
        $calculatorElement
172
            ->waitFor(5, function () use ($channel, $currency) {
173
                return $this->getElement('calculator')->hasField(sprintf('%s %s', $channel->getName(), $currency->getCode()));
174
            })
175
        ;
176
177
        $calculatorElement->fillField(sprintf('%s %s', $channel->getName(), $currency->getCode()), $price);
178
    }
179
180
    /**
181
     * {@inheritdoc}
182
     */
183
    public function activateLanguageTab($locale)
184
    {
185
        if (!$this->getDriver() instanceof Selenium2Driver) {
186
            return;
187
        }
188
189
        $languageTabTitle = $this->getElement('language_tab', ['%locale%' => $locale]);
190
        if (!$languageTabTitle->hasClass('active')) {
191
            $languageTabTitle->click();
192
        }
193
    }
194
195
    /**
196
     * {@inheritdoc}
197
     */
198
    protected function getElement($name, array $parameters = [])
199
    {
200
        if (!isset($parameters['%locale%'])) {
201
            $parameters['%locale%'] = 'en_US';
202
        }
203
204
        return parent::getElement($name, $parameters);
205
    }
206
207
    /**
208
     * {@inheritdoc}
209
     */
210
    protected function getDefinedElements()
211
    {
212
        return array_merge(parent::getDefinedElements(), [
213
            'association_dropdown' => '.field > label:contains("%association%") ~ .product-select',
214
            'association_dropdown_item' => '.field > label:contains("%association%") ~ .product-select > div.menu > div.item:contains("%item%")',
215
            'association_dropdown_item_selected' => '.field > label:contains("%association%") ~ .product-select > a.label:contains("%item%")',
216
            'attribute_delete_button' => '.attribute .label:contains("%attribute%") ~ button',
217
            'attribute_value' => '.attribute .label:contains("%attribute%") ~ input',
218
            'attributes_choice' => 'select[name="sylius_product_attribute_choice"]',
219
            'calculator' => '#sylius_calculator_container',
220
            'code' => '#sylius_product_code',
221
            'form' => 'form[name="sylius_product"]',
222
            'images' => '#sylius_product_images',
223
            'language_tab' => '[data-locale="%locale%"] .title',
224
            'name' => '#sylius_product_translations_%locale%_name',
225
            'price' => '#sylius_product_variant_price',
226
            'price_calculator' => '#sylius_product_variant_pricingCalculator',
227
            'slug' => '#sylius_product_translations_%locale%_slug',
228
            'tab' => '.menu [data-tab="%name%"]',
229
            'toggle_slug_modification_button' => '.toggle-product-slug-modification',
230
        ]);
231
    }
232
233
    /**
234
     * @param int $id
235
     */
236
    private function selectElementFromAttributesDropdown($id)
237
    {
238
        /** @var Selenium2Driver $driver */
239
        $driver = $this->getDriver();
240
        Assert::isInstanceOf($driver, Selenium2Driver::class);
241
242
        $driver->executeScript('$(\'[name="sylius_product_attribute_choice"]\').dropdown(\'show\');');
243
        $driver->executeScript(sprintf('$(\'[name="sylius_product_attribute_choice"]\').dropdown(\'set selected\', %s);', $id));
244
    }
245
246
    /**
247
     * @param int $timeout
248
     */
249
    private function waitForFormElement($timeout = 5)
250
    {
251
        $form = $this->getElement('form');
252
        $this->getDocument()->waitFor($timeout, function () use ($form) {
253
            return false === strpos($form->getAttribute('class'), 'loading');
254
        });
255
    }
256
257
    /**
258
     * @param string $tabName
259
     */
260
    private function clickTabIfItsNotActive($tabName)
261
    {
262
        $attributesTab = $this->getElement('tab', ['%name%' => $tabName]);
263
        if (!$attributesTab->hasClass('active')) {
264
            $attributesTab->click();
265
        }
266
    }
267
268
    /**
269
     * @param string $tabName
270
     */
271
    private function clickTab($tabName)
272
    {
273
        $attributesTab = $this->getElement('tab', ['%name%' => $tabName]);
274
        $attributesTab->click();
275
    }
276
277
    /**
278
     * @return NodeElement
279
     */
280
    private function getLastImageElement()
281
    {
282
        $images = $this->getElement('images');
283
        $items = $images->findAll('css', 'div[data-form-collection="item"]');
284
285
        Assert::notEmpty($items);
286
287
        return end($items);
288
    }
289
290
    /**
291
     * @param string $locale
292
     */
293
    private function waitForSlugGenerationIfNecessary($locale)
294
    {
295
        if ($this->getDriver() instanceof Selenium2Driver) {
296
            $this->getDocument()->waitFor(10, function () use ($locale) {
297
                return '' !== $this->getElement('slug', ['%locale%' => $locale])->getValue();
298
            });
299
        }
300
    }
301
}
302