1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Novaway\CommonContexts\Context; |
4
|
|
|
|
5
|
|
|
use Behat\Mink\Element\DocumentElement; |
6
|
|
|
|
7
|
|
|
class Select2Context extends BaseContext |
8
|
|
|
{ |
9
|
|
|
const DEFAULT_TIMEOUT = 60; |
10
|
|
|
|
11
|
|
|
/** @var int */ |
12
|
|
|
private $timeout; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Constructor |
16
|
|
|
* |
17
|
|
|
* @param int $timeout Timeout for waiting results (in seconds) |
18
|
|
|
*/ |
19
|
|
|
public function __construct($timeout = self::DEFAULT_TIMEOUT) |
20
|
|
|
{ |
21
|
|
|
$this->timeout = $timeout; |
22
|
|
|
} |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Fills in Select2 field with specified |
26
|
|
|
* |
27
|
|
|
* @When /^(?:|I )fill in select2 "(?P<field>(?:[^"]|\\")*)" with "(?P<value>(?:[^"]|\\")*)"$/ |
28
|
|
|
* @When /^(?:|I )fill in select2 "(?P<value>(?:[^"]|\\")*)" for "(?P<field>(?:[^"]|\\")*)"$/ |
29
|
|
|
*/ |
30
|
|
|
public function iFillInSelect2Field($field, $value) |
31
|
|
|
{ |
32
|
|
|
$page = $this->getSession()->getPage(); |
33
|
|
|
|
34
|
|
|
$this->openField($page, $field); |
35
|
|
|
$this->selectValue($page, $field, $value, $this->timeout); |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Fills in Select2 field with specified and wait for results |
40
|
|
|
* |
41
|
|
|
* @When /^(?:|I )fill in select2 "(?P<field>(?:[^"]|\\")*)" with "(?P<value>(?:[^"]|\\")*)" and wait (?P<time>(?:[^"]|\\")*) seconds until results are loaded$/ |
42
|
|
|
* @When /^(?:|I )fill in select2 "(?P<value>(?:[^"]|\\")*)" for "(?P<field>(?:[^"]|\\")*)" and wait (?P<time>(?:[^"]|\\")*) seconds until results are loaded$/ |
43
|
|
|
*/ |
44
|
|
|
public function iFillInSelect2FieldWaitUntilResultsAreLoaded($field, $value, $time) |
45
|
|
|
{ |
46
|
|
|
$page = $this->getSession()->getPage(); |
47
|
|
|
|
48
|
|
|
$this->openField($page, $field); |
49
|
|
|
$this->selectValue($page, $field, $value, $time); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* Fill Select2 input field |
54
|
|
|
* |
55
|
|
|
* @When /^(?:|I )fill in select2 input "(?P<field>(?:[^"]|\\")*)" with "(?P<value>(?:[^"]|\\")*)"$/ |
56
|
|
|
*/ |
57
|
|
|
public function iFillInSelect2InputWith($field, $value) |
58
|
|
|
{ |
59
|
|
|
$page = $this->getSession()->getPage(); |
60
|
|
|
|
61
|
|
|
$this->openField($page, $field); |
62
|
|
|
$this->fillSearchField($page, $field, $value); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Fill Select2 input field and select a value |
67
|
|
|
* |
68
|
|
|
* @When /^(?:|I )fill in select2 input "(?P<field>(?:[^"]|\\")*)" with "(?P<value>(?:[^"]|\\")*)" and select "(?P<entry>(?:[^"]|\\")*)"$/ |
69
|
|
|
*/ |
70
|
|
|
public function iFillInSelect2InputWithAndSelect($field, $value, $entry) |
71
|
|
|
{ |
72
|
|
|
$page = $this->getSession()->getPage(); |
73
|
|
|
|
74
|
|
|
$this->openField($page, $field); |
75
|
|
|
$this->fillSearchField($page, $field, $value); |
76
|
|
|
$this->selectValue($page, $field, $entry, $this->timeout); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Fill Select2 input field |
81
|
|
|
* |
82
|
|
|
* @Then /^(?:|I )should see (?P<num>\d+) choice(?:|s) in select2 "(?P<field>(?:[^"]|\\")*)"$/ |
83
|
|
|
*/ |
84
|
|
|
public function iShouldSeeSelectChoices($field, $num) |
85
|
|
|
{ |
86
|
|
|
$selector = sprintf('#select2-%s-results li', $field); |
87
|
|
|
|
88
|
|
|
$this->assertSession()->elementsCount('css', $selector, intval($num)); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Open Select2 choice list |
93
|
|
|
* |
94
|
|
|
* @param DocumentElement $page |
95
|
|
|
* @param string $field |
96
|
|
|
* @throws \Exception |
97
|
|
|
*/ |
98
|
|
View Code Duplication |
private function openField(DocumentElement $page, $field) |
|
|
|
|
99
|
|
|
{ |
100
|
|
|
// force select2 to be closed |
101
|
|
|
$page->find('css', 'body')->press(); |
102
|
|
|
|
103
|
|
|
$fieldName = sprintf('select[name="%s"] + .select2-container', $field); |
104
|
|
|
|
105
|
|
|
$inputField = $page->find('css', $fieldName); |
106
|
|
|
if (!$inputField) { |
107
|
|
|
throw new \Exception(sprintf('No field "%s" found', $field)); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
$choice = $inputField->find('css', '.select2-selection'); |
111
|
|
|
if (!$choice) { |
112
|
|
|
throw new \Exception(sprintf('No select2 choice found for "%s"', $field)); |
113
|
|
|
} |
114
|
|
|
$choice->press(); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* Fill Select2 search field |
119
|
|
|
* |
120
|
|
|
* @param DocumentElement $page |
121
|
|
|
* @param string $field |
122
|
|
|
* @param string $value |
123
|
|
|
* @throws \Exception |
124
|
|
|
*/ |
125
|
|
|
private function fillSearchField(DocumentElement $page, $field, $value) |
126
|
|
|
{ |
127
|
|
|
$driver = $this->getSession()->getDriver(); |
128
|
|
|
if ('Behat\Mink\Driver\Selenium2Driver' === get_class($driver)) { |
129
|
|
|
// Can't use `$this->getSession()->getPage()->find()` because of https://github.com/minkphp/MinkSelenium2Driver/issues/188 |
130
|
|
|
$select2Input = $this->getSession()->getDriver()->getWebDriverSession()->element('xpath', "//html/descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), ' select2-search__field ')]"); |
|
|
|
|
131
|
|
|
if (!$select2Input) { |
132
|
|
|
throw new \Exception(sprintf('No field "%s" found', $field)); |
133
|
|
|
} |
134
|
|
|
$select2Input->postValue(['value' => [$value]]); |
135
|
|
|
} else { |
136
|
|
|
$select2Input = $page->find('css', '.select2-search__field'); |
137
|
|
|
if (!$select2Input) { |
138
|
|
|
throw new \Exception(sprintf('No input found for "%s"', $field)); |
139
|
|
|
} |
140
|
|
|
$select2Input->setValue($value); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
$this->waitForLoadingResults($this->timeout); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Select value in choice list |
148
|
|
|
* |
149
|
|
|
* @param DocumentElement $page |
150
|
|
|
* @param string $field |
151
|
|
|
* @param string $value |
152
|
|
|
* @param int $time |
153
|
|
|
* @throws \Exception |
154
|
|
|
*/ |
155
|
|
|
private function selectValue(DocumentElement $page, $field, $value, $time) |
156
|
|
|
{ |
157
|
|
|
$this->waitForLoadingResults($time); |
158
|
|
|
|
159
|
|
|
$chosenResults = $page->findAll('css', '.select2-results li'); |
160
|
|
|
foreach ($chosenResults as $result) { |
161
|
|
|
if ($result->getText() == $value) { |
162
|
|
|
$result->click(); |
163
|
|
|
return; |
164
|
|
|
} |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
throw new \Exception(sprintf('Value "%s" not found for "%s"', $value, $field)); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* Wait the end of fetching Select2 results |
172
|
|
|
* |
173
|
|
|
* @param int $time Time to wait in seconds |
174
|
|
|
*/ |
175
|
|
|
private function waitForLoadingResults($time) |
176
|
|
|
{ |
177
|
|
|
for ($i = 0; $i < $time; $i++) { |
178
|
|
|
if (!$this->getSession()->getPage()->find('css', '.select2-results__option.loading-results')) { |
179
|
|
|
return; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
sleep(1); |
183
|
|
|
} |
184
|
|
|
} |
185
|
|
|
} |
186
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.