Completed
Pull Request — 3.1 (#348)
by Piotr
29:38 queued 15:17
created

ListContext::iClickInColumnInFirstRow()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
/**
4
 * (c) FSi sp. z o.o. <[email protected]>
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace FSi\Bundle\AdminBundle\Behat\Context;
13
14
use Behat\Gherkin\Node\TableNode;
15
use FSi\Bundle\AdminBundle\Behat\Element\ListElement;
16
use FSi\Bundle\AdminBundle\Behat\Page\DefaultPage;
17
use SensioLabs\Behat\PageObjectExtension\PageObject\Page;
18
use Symfony\Component\BrowserKit\Client;
19
use Symfony\Component\HttpFoundation\Request;
20
21
class ListContext extends AbstractContext
22
{
23
    /**
24
     * @var DefaultPage
25
     */
26
    private $defaultPage;
27
28
    /**
29
     * @var array
30
     */
31
    private $selectedRows = [];
32
33
    public function __construct(DefaultPage $defaultPage)
34
    {
35
        $this->defaultPage = $defaultPage;
36
    }
37
38
    /**
39
     * @beforeScenario
40
     */
41
    public function clearSelectedRows(): void
42
    {
43
        $this->selectedRows = [];
44
    }
45
46
    /**
47
     * @When I check the row :name
48
     */
49
    public function iCheckTheRow($name)
50
    {
51
        $this->selectedRows[] = $this->getListElement()->getNamedRowId($name);
52
    }
53
54
    /**
55
     * @When /^I press checkbox in first column in first row$/
56
     */
57
    public function iPressCheckboxInFirstColumnInFirstRow()
58
    {
59
        $this->selectedRows[] = $this->getListElement()->getRowId(1);
60
    }
61
62
    /**
63
     * @When /^I press checkbox in first column header$/
64
     */
65
    public function iPressCheckboxInFirstColumnHeader()
66
    {
67
        $this->selectedRows = array_unique(
68
            array_merge($this->selectedRows, $this->getListElement()->getRowsIds())
69
        );
70
    }
71
72
    /**
73
     * @Given I press :action link in actions column of first element at list
74
     */
75
    public function iPressLinkInColumnOfFirstElementAtList($link)
76
    {
77
        $this->getListElement()->clickRowAction(1, $link);
78
    }
79
80
    /**
81
     * @Given I perform the batch action :action
82
     */
83
    public function iPerformBatchAction($action)
84
    {
85
        if ($this->isSeleniumDriverUsed()) {
86
            $this->defaultPage->find('css', '#batch_action_action')->selectOption($action);
87
            $this->defaultPage->findButton('Ok')->click();
88
        } else {
89
            $batchActionUrl = $this->defaultPage
90
                ->find('css', sprintf('#batch_action_action option:contains("%s")', $action))
91
                ->getAttribute('value');
92
            $data = [
93
                'batch_action' => [
94
                    '_token' => $this->defaultPage->find('css', '#batch_action__token')->getAttribute('value')
95
                ]
96
            ];
97
            $i = 0;
98
            foreach ($this->selectedRows as $id) {
99
                $data['indexes'][$i] = $id;
100
                $i++;
101
            }
102
            /** @var Client $client */
103
            $client = $this->getSession()->getDriver()->getClient();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Behat\Mink\Driver\DriverInterface as the method getClient() does only exist in the following implementations of said interface: Behat\Mink\Driver\BrowserKitDriver, Behat\Symfony2Extension\Driver\KernelDriver.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
104
            $client->request(Request::METHOD_POST, $batchActionUrl, $data);
105
        }
106
    }
107
108
    /**
109
     * @Then /^I should see list with following columns$/
110
     */
111
    public function iShouldSeeListWithFollowingColumns(TableNode $table)
112
    {
113
        $elements = $table->getColumn(0);
114
        array_shift($elements);
115
116
        $presentColumns = $this->getListElement()->getColumns();
117
        foreach ($elements as $expectedColumn) {
118
            if (strtolower($expectedColumn) === ListElement::BATCH_COLUMN
119
                && $this->getListElement()->hasBatchColumn()
120
            ) {
121
                continue;
122
            }
123
            if (!in_array($expectedColumn, $presentColumns)) {
124
                throw new \Exception(sprintf('there is no column with name "%s"', $expectedColumn));
125
            }
126
        }
127
    }
128
129
    /**
130
     * @Given /^there are (\d+) elements at list$/
131
     * @Given /^there is (\d+) element at list$/
132
     * @Then /^there should be (\d+) elements at list$/
133
     * @Then /^there should be (\d+) element at list$/
134
     */
135
    public function thereShouldBeElementsAtList($elemetsCount)
136
    {
137
        expect($this->getListElement()->getRowsCount())->toBe($elemetsCount);
138
    }
139
140
    /**
141
     * @Given /^"([^"]*)" column is editable$/
142
     */
143
    public function columnIsEditable($columnHeader)
144
    {
145
        expect($this->getListElement()->isColumnEditable($columnHeader))->toBe(true);
146
    }
147
148
    /**
149
     * @Then I should not see pagination on page :page
150
     */
151
    public function iShouldNotSeePagination(Page $page)
152
    {
153
        expect($page->find('css', 'ul.pagination'))->toBe(null);
154
    }
155
156
    /**
157
     * @Given /^I clicked "([^"]*)" in "([^"]*)" column in first row$/
158
     * @When /^I click "([^"]*)" in "([^"]*)" column in first row$/
159
     */
160
    public function iClickInColumnInFirstRow($link, $columnHeader)
161
    {
162
        $this->getListElement()->getCell($columnHeader, 1)->clickLink($link);
163
    }
164
165
    /**
166
     * @Given /^I clicked edit in "([^"]*)" column in first row$/
167
     * @When /^I click edit in "([^"]*)" column in first row$/
168
     */
169
    public function iClickEditInColumnInFirstRow($columnHeader)
170
    {
171
        $cell = $this->getListElement()->getCell($columnHeader, 1);
172
        $this->getListElement()->click($cell->getXPath());
0 ignored issues
show
Unused Code introduced by
The call to ListElement::click() has too many arguments starting with $cell->getXPath().

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
173
        $cell->find('css', 'a')->click();
174
    }
175
176
    /**
177
     * @Then /^popover with "([^"]*)" field in form should appear$/
178
     */
179
    public function popoverWithFieldInFormShouldAppear($newsTitle)
180
    {
181
        $popover = $this->defaultPage->getPopover();
182
        expect($popover->isVisible())->toBe(true);
183
        expect($popover->findField('Title')->getValue())->toBe($newsTitle);
184
    }
185
186
    /**
187
     * @Then /^popover with empty date field in form should appear$/
188
     */
189
    public function popoverWithEmptyDateFieldInFormShouldAppear()
190
    {
191
        $popover = $this->defaultPage->getPopover();
192
        expect($popover->isVisible())->toBe(true);
193
        expect($popover->findField('Date')->getValue())->toBe('');
194
    }
195
    /**
196
     * @Then /^popover should not be visible anymore$/
197
     */
198
    public function popoverShouldNotBeVisibleAnymore()
199
    {
200
        expect($this->defaultPage->getPopover())->toBe(null);
201
    }
202
203
    /**
204
     * @When /^I fill "([^"]*)" field at popover with "([^"]*)" value$/
205
     */
206
    public function iFillFieldAtPopoverWithValue($field, $value)
207
    {
208
        $this->defaultPage->getPopover()->fillField($field, $value);
209
    }
210
211
    /**
212
     * @Given /^I press "([^"]*)" at popover$/
213
     */
214
    public function iPressAtPopover($button)
215
    {
216
        $this->defaultPage->getPopover()->pressButton($button);
217
    }
218
219
    /**
220
     * @When /^I click X at popover$/
221
     */
222
    public function iClickXAtPopover()
223
    {
224
        $session = $this->defaultPage->getSession();
0 ignored issues
show
Deprecated Code introduced by
The method Behat\Mink\Element\Element::getSession() has been deprecated with message: Accessing the session from the element is deprecated as of 1.6 and will be impossible in 2.0.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
225
        /** @var NodeElement $popover */
226
        $session->wait(1000, 'jQuery(".popover").length > 0');
227
        $popover = $this->defaultPage->getPopover();
228
        $popover->find('css', '.editable-close')->click();
229
        $session->wait(1000, 'jQuery(".popover").length === 0');
230
    }
231
232
    private function getListElement(): ListElement
233
    {
234
        return $this->defaultPage->getElement('ListElement');
235
    }
236
}
237