NavigationGuiPresentationTester   B
last analyzed

Complexity

Total Complexity 47

Size/Duplication

Total Lines 349
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 47
eloc 141
dl 0
loc 349
rs 8.64
c 0
b 0
f 0

37 Methods

Rating   Name   Duplication   Size   Complexity  
A setNameField() 0 3 1
A moveNavigationNode() 0 5 1
A cleanUpNavigationTree() 0 18 3
A seeSuccessfulOrderSaveMessage() 0 6 1
A waitForNavigationTree() 0 4 1
A clickAddChildNodeButton() 0 3 1
A saveNavigationTreeOrder() 0 3 1
A submitCreateNodeFormWithoutType() 0 6 1
A seeNavigationNodeHierarchy() 0 7 1
A deleteFirstNavigationRow() 0 3 1
A seeSuccessMessage() 0 9 1
A submitCreateNodeFormWithCmsPageTypeWithFormData() 0 13 2
A submitNavigationForm() 0 3 1
A submitDeleteNavigationForm() 0 3 1
A clickNode() 0 3 1
A generateUrlByAvailableLocaleTransfers() 0 11 2
A clickRemoveNodeButton() 0 3 1
A switchToNodeForm() 0 4 1
A seeNumberOfNavigationNodes() 0 3 1
A seeMatches() 0 3 1
A prepareTestNavigationTreeEntities() 0 9 2
A submitCreateNodeFormWithExternalUrlType() 0 9 1
A clickEditFirstRowInList() 0 3 1
A clickRootNode() 0 3 1
A submitCreateNodeFormWithCmsPageType() 0 9 1
A seeNavigationNodeHierarchyByChildNodeName() 0 6 1
A repeatUnstableActions() 0 13 4
A createNavigationNodesRecursively() 0 14 2
A activateFirstNavigationRow() 0 3 1
A switchToNavigationTree() 0 4 1
A checkIsActiveField() 0 6 2
A submitUpdateNodeToCategoryType() 0 8 1
A setKeyField() 0 3 1
A expandLocalizedForm() 0 3 1
A getIdLocale() 0 3 1
A prepareTestNavigationEntity() 0 10 1
A findNavigationByIdNavigation() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like NavigationGuiPresentationTester often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use NavigationGuiPresentationTester, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * This file is part of the Spryker Commerce OS.
5
 * For full license information, please view the LICENSE file that was distributed with this source code.
6
 */
7
8
declare(strict_types = 1);
9
10
namespace PyzTest\Zed\NavigationGui;
11
12
use Codeception\Actor;
13
use Exception;
14
use Generated\Shared\Transfer\NavigationTreeNodeTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfe...igationTreeNodeTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use Generated\Shared\Transfer\NavigationTreeTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\NavigationTreeTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
use Orm\Zed\Navigation\Persistence\SpyNavigation;
17
use Orm\Zed\Navigation\Persistence\SpyNavigationQuery;
18
19
/**
20
 * Inherited Methods
21
 *
22
 * @method void wantToTest($text)
23
 * @method void wantTo($text)
24
 * @method void execute($callable)
25
 * @method void expectTo($prediction)
26
 * @method void expect($prediction)
27
 * @method void amGoingTo($argumentation)
28
 * @method void am($role)
29
 * @method void lookForwardTo($achieveValue)
30
 * @method void comment($description)
31
 * @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
32
 *
33
 * @SuppressWarnings(\PyzTest\Zed\NavigationGui\PHPMD)
34
 */
35
class NavigationGuiPresentationTester extends Actor
36
{
37
    use _generated\NavigationGuiPresentationTesterActions;
0 ignored issues
show
Bug introduced by
The type PyzTest\Zed\NavigationGu...esentationTesterActions was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
38
39
    public const ROOT_NODE_ANCHOR_SELECTOR = '#navigation-node-0_anchor';
40
41
    public const CHILD_NODE_ANCHOR_SELECTOR = '#navigation-node-%d_anchor';
42
43
    public const NAVIGATION_NODE_SELECTOR = '.jstree-node';
44
45
    public const NAVIGATION_TREE_SELECTOR = '#navigation-tree';
46
47
    public const NAVIGATION_TREE_SAVE_BUTTON_SELECTOR = '#navigation-tree-save-btn';
48
49
    public const REMOVE_NODE_BUTTON_SELECTOR = '#remove-selected-node-btn';
50
51
    public const ADD_CHILD_NODE_BUTTON_SELECTOR = '#add-child-node-btn';
52
53
    public const LOCALIZED_FORM_CONTAINER_SELECTOR = '#localized_attributes_container-%s .collapse-link';
54
55
    public const NODE_CHILD_SELECTOR = '#navigation-node-%d #navigation-node-%d';
56
57
    public const NODE_NAME_CHILD_SELECTOR = "//*[@id=\"navigation-node-%d\"]//*[text()[contains(.,'%s')]]";
58
59
    public const NODE_FORM_IFRAME_NAME = 'navigation-node-form-iframe';
60
61
    public const SUCCESS_MESSAGE_SELECTOR = '.flash-messages .alert-success';
62
63
    public const SWEET_ALERT_SELECTOR = '.sweet-alert';
64
65
    public const SWEET_ALERT_CONFIRM_SELECTOR = '.sweet-alert button.confirm';
66
67
    public const NODE_FORM_SELECTOR = 'form';
68
69
    public const NODE_UPDATE_FORM_SELECTOR = '//form[@name="navigation_node"]';
70
71
    public const FLASH_MESSAGE_TEXT_SELECTOR = '//div[@class="flash-messages"]/div';
72
73
    public const NAVIGATION_DELETE_FORM_SELECTOR = '//*[@id="navigation-table"]/tbody/tr/td[5]/form[1]';
74
75
    public const NAVIGATION_ROW_ACTIVE_LINK_SELECTOR = '//*[@id="navigation-table"]/tbody/tr[1]/td[5]/a[2]';
76
77
    public function setNameField(string $value): void
78
    {
79
        $this->fillField('//*[@id="navigation_name"]', $value);
80
    }
81
82
    public function setKeyField(string $value): void
83
    {
84
        $this->fillField('//*[@id="navigation_key"]', $value);
85
    }
86
87
    public function checkIsActiveField(bool $checked): void
88
    {
89
        if ($checked) {
90
            $this->checkOption('//*[@id="navigation_is_active"]');
91
        } else {
92
            $this->uncheckOption('//*[@id="navigation_is_active"]');
93
        }
94
    }
95
96
    public function submitNavigationForm(): void
97
    {
98
        $this->click('//*[@id="navigation-save-btn"]');
99
    }
100
101
    public function submitDeleteNavigationForm(): void
102
    {
103
        $this->click('//*[@id="delete_navigation_form_submit"]');
104
    }
105
106
    public function seeMatches(string $pattern, string $value): void
107
    {
108
        $this->assertRegExp($pattern, $value);
109
    }
110
111
    public function clickEditFirstRowInList(): void
112
    {
113
        $this->click('//*[@id="navigation-table"]/tbody/tr[1]/td[5]/a');
114
    }
115
116
    public function seeSuccessMessage(string $expectedMessagePattern): string
117
    {
118
        $this->waitForElementVisible(static::FLASH_MESSAGE_TEXT_SELECTOR, 90);
119
        $successMessage = $this->grabTextFrom(static::FLASH_MESSAGE_TEXT_SELECTOR);
120
        $this->seeMatches($expectedMessagePattern, $successMessage);
121
122
        preg_match($expectedMessagePattern, $successMessage, $matches);
123
124
        return $matches[1];
125
    }
126
127
    public function activateFirstNavigationRow(): void
128
    {
129
        $this->click(static::NAVIGATION_ROW_ACTIVE_LINK_SELECTOR);
130
    }
131
132
    public function deleteFirstNavigationRow(): void
133
    {
134
        $this->submitForm(static::NAVIGATION_DELETE_FORM_SELECTOR, []);
135
    }
136
137
    public function prepareTestNavigationEntity(): int
138
    {
139
        $navigationEntity = new SpyNavigation();
140
        $navigationEntity
141
            ->setName('Acceptance navigation (2)')
142
            ->setKey('acceptance2')
143
            ->setIsActive(true)
144
            ->save();
145
146
        return $navigationEntity->getIdNavigation();
147
    }
148
149
    public function expandLocalizedForm(string $localeName): void
150
    {
151
        $this->click(sprintf(self::LOCALIZED_FORM_CONTAINER_SELECTOR, $localeName));
152
    }
153
154
    public function clickRootNode(): void
155
    {
156
        $this->click(self::ROOT_NODE_ANCHOR_SELECTOR);
157
    }
158
159
    public function clickNode(int $idNavigationNode): void
160
    {
161
        $this->click(sprintf(self::CHILD_NODE_ANCHOR_SELECTOR, $idNavigationNode));
162
    }
163
164
    public function waitForNavigationTree(): void
165
    {
166
        $this->waitForElement(self::NAVIGATION_TREE_SELECTOR);
167
        $this->wait(5);
168
    }
169
170
    public function seeNumberOfNavigationNodes(int $count): void
171
    {
172
        $this->seeNumberOfElements(self::NAVIGATION_NODE_SELECTOR, $count);
173
    }
174
175
    public function seeNavigationNodeHierarchy(int $idParentNavigationNode, int $idChildNavigationNode): void
176
    {
177
        $this->waitForElement(sprintf(
178
            self::NODE_CHILD_SELECTOR,
179
            $idParentNavigationNode,
180
            $idChildNavigationNode,
181
        ), 1);
182
    }
183
184
    public function seeNavigationNodeHierarchyByChildNodeName(int $idParentNavigationNode, string $childNavigationNodeName): void
185
    {
186
        $this->seeElement(sprintf(
187
            self::NODE_NAME_CHILD_SELECTOR,
188
            $idParentNavigationNode,
189
            $childNavigationNodeName,
190
        ));
191
    }
192
193
    public function moveNavigationNode(int $idNavigationNode, int $idTargetNavigationNode): void
194
    {
195
        $this->dragAndDrop(
196
            sprintf(self::CHILD_NODE_ANCHOR_SELECTOR, $idNavigationNode),
197
            sprintf(self::CHILD_NODE_ANCHOR_SELECTOR, $idTargetNavigationNode),
198
        );
199
    }
200
201
    public function saveNavigationTreeOrder(): void
202
    {
203
        $this->click(self::NAVIGATION_TREE_SAVE_BUTTON_SELECTOR);
204
    }
205
206
    public function seeSuccessfulOrderSaveMessage(string $message): void
207
    {
208
        $this->waitForElement(self::SWEET_ALERT_SELECTOR, 5);
209
        $this->wait(1);
210
        $this->see($message);
211
        $this->click(self::SWEET_ALERT_CONFIRM_SELECTOR);
212
    }
213
214
    public function switchToNodeForm(): void
215
    {
216
        $this->switchToIFrame(self::NODE_FORM_IFRAME_NAME);
217
        $this->waitForElement(self::NODE_FORM_SELECTOR, 5);
218
    }
219
220
    public function switchToNavigationTree(): void
221
    {
222
        $this->switchToIFrame();
223
        $this->waitForNavigationTree();
224
    }
225
226
    public function clickRemoveNodeButton(): void
227
    {
228
        $this->click(self::REMOVE_NODE_BUTTON_SELECTOR);
229
    }
230
231
    public function clickAddChildNodeButton(): void
232
    {
233
        $this->click(self::ADD_CHILD_NODE_BUTTON_SELECTOR);
234
    }
235
236
    public function submitCreateNodeFormWithoutType(string $title): void
237
    {
238
        $this->submitForm(self::NODE_FORM_SELECTOR, [
239
            'navigation_node[navigation_node_localized_attributes][0][title]' => $title,
240
            'navigation_node[navigation_node_localized_attributes][1][title]' => $title,
241
            'navigation_node[is_active]' => true,
242
        ]);
243
    }
244
245
    public function submitCreateNodeFormWithExternalUrlType(string $title, string $externalUrl): void
246
    {
247
        $this->submitForm(self::NODE_FORM_SELECTOR, [
248
            'navigation_node[node_type]' => 'external_url',
249
            'navigation_node[navigation_node_localized_attributes][0][external_url]' => $externalUrl,
250
            'navigation_node[navigation_node_localized_attributes][1][external_url]' => $externalUrl,
251
            'navigation_node[navigation_node_localized_attributes][0][title]' => $title,
252
            'navigation_node[navigation_node_localized_attributes][1][title]' => $title,
253
            'navigation_node[is_active]' => true,
254
        ]);
255
    }
256
257
    public function submitUpdateNodeToCategoryType(string $categoryUrl_en_US, string $categoryUrl_de_DE): void
258
    {
259
        $this->selectOption('#navigation_node_node_type', 'Category');
260
261
        $this->fillField('//form[@name=\'navigation_node\']//input[@name=\'navigation_node[navigation_node_localized_attributes][0][category_url]\']', $categoryUrl_en_US);
262
        $this->fillField('//form[@name=\'navigation_node\']//input[@name=\'navigation_node[navigation_node_localized_attributes][1][category_url]\']', $categoryUrl_de_DE);
263
264
        $this->click('//*[@id="navigation-node-form-submit"]');
265
    }
266
267
    public function submitCreateNodeFormWithCmsPageType(string $title, string $cmsPageUrl_en_US, string $cmsPageUrl_de_DE): void
268
    {
269
        $this->submitForm(self::NODE_FORM_SELECTOR, [
270
            'navigation_node[node_type]' => 'cms_page',
271
            'navigation_node[navigation_node_localized_attributes][0][title]' => $title,
272
            'navigation_node[navigation_node_localized_attributes][0][cms_page_url]' => $cmsPageUrl_en_US,
273
            'navigation_node[navigation_node_localized_attributes][1][title]' => $title,
274
            'navigation_node[navigation_node_localized_attributes][1][cms_page_url]' => $cmsPageUrl_de_DE,
275
            'navigation_node[is_active]' => true,
276
        ]);
277
    }
278
279
    public function prepareTestNavigationTreeEntities(NavigationTreeTransfer $navigationTreeTransfer): NavigationTreeTransfer
280
    {
281
        $navigationTransfer = $this->getLocator()->navigation()->facade()->createNavigation($navigationTreeTransfer->getNavigation());
282
283
        foreach ($navigationTreeTransfer->getNodes() as $navigationTreeNodeTransfer) {
284
            $this->createNavigationNodesRecursively($navigationTreeNodeTransfer, $navigationTransfer->getIdNavigation());
285
        }
286
287
        return $navigationTreeTransfer;
288
    }
289
290
    protected function createNavigationNodesRecursively(
291
        NavigationTreeNodeTransfer $navigationTreeNodeTransfer,
292
        int $idNavigation,
293
        ?int $idParentNavigationNode = null,
294
    ): void {
295
        $navigationNodeTransfer = $navigationTreeNodeTransfer->getNavigationNode();
296
        $navigationNodeTransfer
297
            ->setFkNavigation($idNavigation)
298
            ->setFkParentNavigationNode($idParentNavigationNode);
299
300
        $navigationNodeTransfer = $this->getLocator()->navigation()->facade()->createNavigationNode($navigationNodeTransfer);
301
302
        foreach ($navigationTreeNodeTransfer->getChildren() as $childNavigationTreeNodeTransfer) {
303
            $this->createNavigationNodesRecursively($childNavigationTreeNodeTransfer, $idNavigation, $navigationNodeTransfer->getIdNavigationNode());
304
        }
305
    }
306
307
    public function getIdLocale(string $locale): int
308
    {
309
        return $this->getLocator()->locale()->facade()->getLocale($locale)->getIdLocale();
310
    }
311
312
    public function cleanUpNavigationTree(NavigationTreeTransfer $navigationTreeTransfer): void
313
    {
314
        $navigationEntity = $this->findNavigationByIdNavigation(
315
            $navigationTreeTransfer->getNavigationOrFail()->getIdNavigationOrFail(),
316
        );
317
318
        if (!$navigationEntity) {
319
            return;
320
        }
321
322
        $navigationNodeEntities = $navigationEntity->getSpyNavigationNodes();
323
324
        foreach ($navigationNodeEntities as $navigationNodeEntity) {
325
            $navigationNodeEntity->getSpyNavigationNodeLocalizedAttributess()->delete();
326
        }
327
328
        $navigationNodeEntities->delete();
329
        $navigationEntity->delete();
330
    }
331
332
    protected function findNavigationByIdNavigation(int $idNavigation): ?SpyNavigation
333
    {
334
        return (new SpyNavigationQuery())->findOneByIdNavigation($idNavigation);
335
    }
336
337
    public function submitCreateNodeFormWithCmsPageTypeWithFormData(array $data): void
338
    {
339
        $formData = [
340
            'navigation_node[node_type]' => 'cms_page',
341
            'navigation_node[is_active]' => true,
342
        ];
343
        foreach ($data as $index => $localizedData) {
344
            $titleKey = sprintf('navigation_node[navigation_node_localized_attributes][%s][title]', $index);
345
            $urlKey = sprintf('navigation_node[navigation_node_localized_attributes][%s][cms_page_url]', $index);
346
            $formData[$titleKey] = $localizedData['title'];
347
            $formData[$urlKey] = $localizedData['url'];
348
        }
349
        $this->submitForm(static::NODE_FORM_SELECTOR, $formData);
350
    }
351
352
    /**
353
     * @param string $defaultSlug
354
     * @param array<string> $localizedSlugs
355
     *
356
     * @return array<string>
357
     */
358
    public function generateUrlByAvailableLocaleTransfers(string $defaultSlug, array $localizedSlugs): array
359
    {
360
        $localeTransfers = $this->getLocator()->locale()->facade()->getLocaleCollection();
361
362
        $localeUrls = [];
363
        foreach ($localeTransfers as $localeTransfer) {
364
            $localePrefix = substr($localeTransfer->getLocaleName(), 0, 2);
365
            $localeUrls[] = sprintf('/%s/%s', $localePrefix, $localizedSlugs[$localeTransfer->getLocaleName()] ?? $defaultSlug);
366
        }
367
368
        return $localeUrls;
369
    }
370
371
    public function repeatUnstableActions(callable $callable, int $maxCount = 10, bool $verbose = false): void
372
    {
373
        $count = 0;
374
375
        while ($count < $maxCount) {
376
            try {
377
                $callable();
378
379
                break;
380
            } catch (Exception $exception) {
381
                $count++;
382
                if ($verbose) {
383
                    echo "Try: {$count}: ";
384
                }
385
            }
386
        }
387
    }
388
}
389