Completed
Push — 1.4-symfony-4.2 ( 36fb3d...ea4277 )
by Kamil
23:20 queued 12:54
created

CreateSimpleProductPage::getDefinedElements()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 9.472
c 0
b 0
f 0
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\Page\Admin\Product;
15
16
use Behat\Mink\Driver\Selenium2Driver;
17
use Behat\Mink\Element\NodeElement;
18
use Sylius\Behat\Behaviour\SpecifiesItsCode;
19
use Sylius\Behat\Page\Admin\Crud\CreatePage as BaseCreatePage;
20
use Sylius\Behat\Service\SlugGenerationHelper;
21
use Sylius\Component\Product\Model\ProductAssociationTypeInterface;
22
use Webmozart\Assert\Assert;
23
24
class CreateSimpleProductPage extends BaseCreatePage implements CreateSimpleProductPageInterface
0 ignored issues
show
Bug introduced by
There is one abstract method getDocument in this class; you could implement it, or declare this class as abstract.
Loading history...
25
{
26
    use SpecifiesItsCode;
27
28
    public function getRouteName(): string
29
    {
30
        return parent::getRouteName() . '_simple';
31
    }
32
33
    public function nameItIn(string $name, string $localeCode): void
34
    {
35
        $this->activateLanguageTab($localeCode);
36
        $this->getElement('name', ['%locale%' => $localeCode])->setValue($name);
37
38
        if ($this->getDriver() instanceof Selenium2Driver) {
39
            SlugGenerationHelper::waitForSlugGeneration(
40
                $this->getSession(),
41
                $this->getElement('slug', ['%locale%' => $localeCode])
42
            );
43
        }
44
    }
45
46
    public function specifySlugIn(?string $slug, string $locale): void
47
    {
48
        $this->activateLanguageTab($locale);
49
50
        $this->getElement('slug', ['%locale%' => $locale])->setValue($slug);
51
    }
52
53
    public function specifyPrice(string $channelName, string $price): void
54
    {
55
        $this->getElement('price', ['%channelName%' => $channelName])->setValue($price);
56
    }
57
58
    public function specifyOriginalPrice(string $channelName, int $originalPrice): void
59
    {
60
        $this->getElement('original_price', ['%channelName%' => $channelName])->setValue($originalPrice);
61
    }
62
63
    public function addAttribute(string $attributeName, string $value, string $localeCode): void
64
    {
65
        $this->clickTabIfItsNotActive('attributes');
66
        $this->clickLocaleTabIfItsNotActive($localeCode);
67
68
        $attributeOption = $this->getElement('attributes_choice')->find('css', sprintf('option:contains("%s")', $attributeName));
69
        $this->selectElementFromAttributesDropdown($attributeOption->getAttribute('value'));
70
71
        $this->getDocument()->pressButton('Add attributes');
72
        $this->waitForFormElement();
73
74
        $this->getElement('attribute_value', ['%attributeName%' => $attributeName, '%localeCode%' => $localeCode])->setValue($value);
75
    }
76
77
    public function getAttributeValidationErrors(string $attributeName, string $localeCode): string
78
    {
79
        $this->clickTabIfItsNotActive('attributes');
80
        $this->clickLocaleTabIfItsNotActive($localeCode);
81
82
        $validationError = $this->getElement('attribute')->find('css', '.sylius-validation-error');
83
84
        return $validationError->getText();
85
    }
86
87
    public function removeAttribute(string $attributeName, string $localeCode): void
88
    {
89
        $this->clickTabIfItsNotActive('attributes');
90
91
        $this->getElement('attribute_delete_button', ['%attributeName%' => $attributeName, '%localeCode%' => $localeCode])->press();
92
    }
93
94
    public function attachImage(string $path, string $type = null): void
95
    {
96
        $this->clickTabIfItsNotActive('media');
97
98
        $filesPath = $this->getParameter('files_path');
99
100
        $this->getDocument()->clickLink('Add');
101
102
        $imageForm = $this->getLastImageElement();
103
        if (null !== $type) {
104
            $imageForm->fillField('Type', $type);
105
        }
106
107
        $imageForm->find('css', 'input[type="file"]')->attachFile($filesPath . $path);
108
    }
109
110
    public function associateProducts(ProductAssociationTypeInterface $productAssociationType, array $productsNames): void
111
    {
112
        $this->clickTab('associations');
113
114
        Assert::isInstanceOf($this->getDriver(), Selenium2Driver::class);
115
116
        $dropdown = $this->getElement('association_dropdown', [
117
            '%association%' => $productAssociationType->getName(),
118
        ]);
119
        $dropdown->click();
120
121
        foreach ($productsNames as $productName) {
122
            $dropdown->waitFor(5, function () use ($productName, $productAssociationType) {
123
                return $this->hasElement('association_dropdown_item', [
124
                    '%association%' => $productAssociationType->getName(),
125
                    '%item%' => $productName,
126
                ]);
127
            });
128
129
            $item = $this->getElement('association_dropdown_item', [
130
                '%association%' => $productAssociationType->getName(),
131
                '%item%' => $productName,
132
            ]);
133
            $item->click();
134
        }
135
    }
136
137
    public function removeAssociatedProduct(string $productName, ProductAssociationTypeInterface $productAssociationType): void
138
    {
139
        $this->clickTabIfItsNotActive('associations');
140
141
        $item = $this->getElement('association_dropdown_item_selected', [
142
            '%association%' => $productAssociationType->getName(),
143
            '%item%' => $productName,
144
        ]);
145
        $item->find('css', 'i.delete')->click();
146
    }
147
148
    public function choosePricingCalculator(string $name): void
149
    {
150
        $this->getElement('price_calculator')->selectOption($name);
151
    }
152
153
    public function checkChannel(string $channelName): void
154
    {
155
        $this->getElement('channel_checkbox', ['%channelName%' => $channelName])->check();
156
    }
157
158
    public function activateLanguageTab(string $locale): void
159
    {
160
        if (!$this->getDriver() instanceof Selenium2Driver) {
161
            return;
162
        }
163
164
        $languageTabTitle = $this->getElement('language_tab', ['%locale%' => $locale]);
165
        if (!$languageTabTitle->hasClass('active')) {
166
            $languageTabTitle->click();
167
        }
168
    }
169
170
    public function selectShippingCategory(string $shippingCategoryName): void
171
    {
172
        $this->getElement('shipping_category')->selectOption($shippingCategoryName);
173
    }
174
175
    public function setShippingRequired(bool $isShippingRequired): void
176
    {
177
        if ($isShippingRequired) {
178
            $this->getElement('shipping_required')->check();
179
180
            return;
181
        }
182
183
        $this->getElement('shipping_required')->uncheck();
184
    }
185
186
    protected function getElement(string $name, array $parameters = []): NodeElement
187
    {
188
        if (!isset($parameters['%locale%'])) {
189
            $parameters['%locale%'] = 'en_US';
190
        }
191
192
        return parent::getElement($name, $parameters);
193
    }
194
195
    protected function getDefinedElements(): array
196
    {
197
        return array_merge(parent::getDefinedElements(), [
198
            'association_dropdown' => '.field > label:contains("%association%") ~ .product-select',
199
            'association_dropdown_item' => '.field > label:contains("%association%") ~ .product-select > div.menu > div.item:contains("%item%")',
200
            'association_dropdown_item_selected' => '.field > label:contains("%association%") ~ .product-select > a.label:contains("%item%")',
201
            'attribute' => '.attribute',
202
            'attribute_delete_button' => '.tab[data-tab="%localeCode%"] .attribute .label:contains("%attributeName%") ~ button',
203
            'attribute_value' => '.tab[data-tab="%localeCode%"] .attribute .label:contains("%attributeName%") ~ input',
204
            'attributes_choice' => '#sylius_product_attribute_choice',
205
            'channel_checkbox' => '.checkbox:contains("%channelName%") input',
206
            'channel_pricings' => '#sylius_product_variant_channelPricings',
207
            'code' => '#sylius_product_code',
208
            'form' => 'form[name="sylius_product"]',
209
            'images' => '#sylius_product_images',
210
            'language_tab' => '[data-locale="%locale%"] .title',
211
            'locale_tab' => '#attributesContainer .menu [data-tab="%localeCode%"]',
212
            'name' => '#sylius_product_translations_%locale%_name',
213
            'price' => '#sylius_product_variant_channelPricings > .field:contains("%channelName%") input[name$="[price]"]',
214
            'original_price' => '#sylius_product_variant_channelPricings > .field:contains("%channelName%") input[name$="[originalPrice]"]',
215
            'price_calculator' => '#sylius_product_variant_pricingCalculator',
216
            'shipping_category' => '#sylius_product_variant_shippingCategory',
217
            'shipping_required' => '#sylius_product_variant_shippingRequired',
218
            'slug' => '#sylius_product_translations_%locale%_slug',
219
            'tab' => '.menu [data-tab="%name%"]',
220
            'toggle_slug_modification_button' => '.toggle-product-slug-modification',
221
        ]);
222
    }
223
224
    private function selectElementFromAttributesDropdown(string $id): void
225
    {
226
        /** @var Selenium2Driver $driver */
227
        $driver = $this->getDriver();
228
        Assert::isInstanceOf($driver, Selenium2Driver::class);
229
230
        $driver->executeScript('$(\'#sylius_product_attribute_choice\').dropdown(\'show\');');
231
        $driver->executeScript(sprintf('$(\'#sylius_product_attribute_choice\').dropdown(\'set selected\', \'%s\');', $id));
232
    }
233
234
    private function waitForFormElement(int $timeout = 5): void
235
    {
236
        $form = $this->getElement('form');
237
        $this->getDocument()->waitFor($timeout, function () use ($form) {
238
            return false === strpos($form->getAttribute('class'), 'loading');
239
        });
240
    }
241
242
    private function clickTabIfItsNotActive(string $tabName): void
243
    {
244
        $attributesTab = $this->getElement('tab', ['%name%' => $tabName]);
245
        if (!$attributesTab->hasClass('active')) {
246
            $attributesTab->click();
247
        }
248
    }
249
250
    private function clickTab(string $tabName): void
251
    {
252
        $attributesTab = $this->getElement('tab', ['%name%' => $tabName]);
253
        $attributesTab->click();
254
    }
255
256
    private function clickLocaleTabIfItsNotActive(string $localeCode): void
257
    {
258
        $localeTab = $this->getElement('locale_tab', ['%localeCode%' => $localeCode]);
259
        if (!$localeTab->hasClass('active')) {
260
            $localeTab->click();
261
        }
262
    }
263
264
    private function getLastImageElement(): NodeElement
265
    {
266
        $images = $this->getElement('images');
267
        $items = $images->findAll('css', 'div[data-form-collection="item"]');
268
269
        Assert::notEmpty($items);
270
271
        return end($items);
272
    }
273
}
274