|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Acquia\DFExtension\Context; |
|
4
|
|
|
|
|
5
|
|
|
use Behat\Mink\Driver\Selenium2Driver; |
|
6
|
|
|
use Behat\Mink\Element\ElementInterface; |
|
7
|
|
|
use Behat\Mink\Exception\ExpectationException; |
|
8
|
|
|
use Drupal\Component\Utility\Random; |
|
9
|
|
|
use Drupal\DrupalExtension\Context\DrupalSubContextBase; |
|
10
|
|
|
use WebDriver\Exception\NoAlertOpenError; |
|
11
|
|
|
|
|
12
|
|
|
/** |
|
13
|
|
|
* A context with miscellaneous helpers. |
|
14
|
|
|
*/ |
|
15
|
|
|
class UtilityContext extends DrupalSubContextBase { |
|
16
|
|
|
|
|
17
|
|
|
/** |
|
18
|
|
|
* Asserts that a form field is not present. |
|
19
|
|
|
* |
|
20
|
|
|
* @param string $field |
|
21
|
|
|
* The field locator. |
|
22
|
|
|
* |
|
23
|
|
|
* @Then I should not see a :field field |
|
24
|
|
|
*/ |
|
25
|
|
|
public function assertFieldNotExists($field) { |
|
26
|
|
|
$this->assertSession()->fieldNotExists($field); |
|
27
|
|
|
} |
|
28
|
|
|
|
|
29
|
|
|
/** |
|
30
|
|
|
* Asserts that a certain number of elements match a CSS selector. |
|
31
|
|
|
* |
|
32
|
|
|
* @param string $selector |
|
33
|
|
|
* The selector. |
|
34
|
|
|
* @param int $count |
|
35
|
|
|
* The number of elements expected to match the selector. |
|
36
|
|
|
* |
|
37
|
|
|
* @throws ExpectationException |
|
38
|
|
|
* If the number of elements that match the selector is not the expected |
|
39
|
|
|
* number. |
|
40
|
|
|
* |
|
41
|
|
|
* @Then :count element(s) should match :selector |
|
42
|
|
|
*/ |
|
43
|
|
View Code Duplication |
public function assertSelectorMatch($selector, $count) { |
|
|
|
|
|
|
44
|
|
|
$session = $this->getSession(); |
|
45
|
|
|
|
|
46
|
|
|
$result = count($session->getPage()->findAll('css', $selector)); |
|
47
|
|
|
|
|
48
|
|
|
if ($result != $count) { |
|
49
|
|
|
throw new ExpectationException( |
|
50
|
|
|
'"' . $selector . '" matched ' . $result . ' element(s), expected ' . $count . '.', |
|
51
|
|
|
$session->getDriver() |
|
52
|
|
|
); |
|
53
|
|
|
} |
|
54
|
|
|
} |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* Asserts that a minimum number of elements match a CSS selector. |
|
58
|
|
|
* |
|
59
|
|
|
* @param string $selector |
|
60
|
|
|
* The selector. |
|
61
|
|
|
* @param int $count |
|
62
|
|
|
* The number of elements expected to match the selector. |
|
63
|
|
|
* |
|
64
|
|
|
* @throws ExpectationException |
|
65
|
|
|
* If the number of elements that match the selector is less than expected. |
|
66
|
|
|
* |
|
67
|
|
|
* @Then at least :count element(s) should match :selector |
|
68
|
|
|
*/ |
|
69
|
|
View Code Duplication |
public function assertSelectorMatchAtLeast($selector, $count) { |
|
|
|
|
|
|
70
|
|
|
$session = $this->getSession(); |
|
71
|
|
|
|
|
72
|
|
|
$result = count($session->getPage()->findAll('css', $selector)); |
|
73
|
|
|
|
|
74
|
|
|
if ($result < $count) { |
|
75
|
|
|
throw new ExpectationException( |
|
76
|
|
|
'"' . $selector . '" matched ' . $result . ' element(s), expected at least ' . $count . '.', |
|
77
|
|
|
$session->getDriver() |
|
78
|
|
|
); |
|
79
|
|
|
} |
|
80
|
|
|
} |
|
81
|
|
|
|
|
82
|
|
|
/** |
|
83
|
|
|
* Asserts that no elements match a CSS selector. |
|
84
|
|
|
* |
|
85
|
|
|
* @param string $selector |
|
86
|
|
|
* The selector. |
|
87
|
|
|
* |
|
88
|
|
|
* @Then no elements should match :selector |
|
89
|
|
|
* @Then nothing should match :selector |
|
90
|
|
|
*/ |
|
91
|
|
|
public function assertSelectorMatchNothing($selector) { |
|
92
|
|
|
$this->assertSelectorMatch($selector, 0); |
|
93
|
|
|
} |
|
94
|
|
|
|
|
95
|
|
|
/** |
|
96
|
|
|
* Asserts than an element is empty. |
|
97
|
|
|
* |
|
98
|
|
|
* @param string $selector |
|
99
|
|
|
* The element's CSS selector. |
|
100
|
|
|
* |
|
101
|
|
|
* @throws ExpectationException |
|
102
|
|
|
* If the element has any HTML content. |
|
103
|
|
|
* |
|
104
|
|
|
* @Then the :selector element(s) should be empty |
|
105
|
|
|
*/ |
|
106
|
|
|
public function assertElementIsEmpty($selector) { |
|
107
|
|
|
$content = $this->assertSession()->elementExists('css', $selector)->getHtml(); |
|
108
|
|
|
|
|
109
|
|
|
if (trim($content)) { |
|
110
|
|
|
throw new ExpectationException( |
|
111
|
|
|
'Expected ' . $selector . ' to be empty but it is not.', |
|
112
|
|
|
$this->getSession()->getDriver() |
|
113
|
|
|
); |
|
114
|
|
|
} |
|
115
|
|
|
} |
|
116
|
|
|
|
|
117
|
|
|
/** |
|
118
|
|
|
* Clears a field. |
|
119
|
|
|
* |
|
120
|
|
|
* @param string $field |
|
121
|
|
|
* The field to clear. |
|
122
|
|
|
* @param ElementInterface $container |
|
123
|
|
|
* (optional) The containing element. |
|
124
|
|
|
* |
|
125
|
|
|
* @When I clear :field |
|
126
|
|
|
*/ |
|
127
|
|
|
public function clearField($field, ElementInterface $container = NULL) { |
|
128
|
|
|
$this->assertSession()->fieldExists($field, $container)->setValue(FALSE); |
|
|
|
|
|
|
129
|
|
|
} |
|
130
|
|
|
|
|
131
|
|
|
/** |
|
132
|
|
|
* Finds a collapsible details element by its summary text. |
|
133
|
|
|
* |
|
134
|
|
|
* @param string $summary_text |
|
135
|
|
|
* The summary text. |
|
136
|
|
|
* |
|
137
|
|
|
* @return \Behat\Mink\Element\NodeElement|null |
|
138
|
|
|
* The details element, or NULL if it was not found. |
|
139
|
|
|
*/ |
|
140
|
|
|
public function findCollapsible($summary_text) { |
|
141
|
|
|
/** @var \Behat\Mink\Element\NodeElement[] $elements */ |
|
142
|
|
|
$elements = $this |
|
143
|
|
|
->getSession() |
|
144
|
|
|
->getPage() |
|
145
|
|
|
->findAll('css', 'details > summary'); |
|
146
|
|
|
|
|
147
|
|
|
foreach ($elements as $element) { |
|
148
|
|
|
if ($element->getText() == $summary_text) { |
|
149
|
|
|
return $element->getParent(); |
|
150
|
|
|
} |
|
151
|
|
|
} |
|
152
|
|
|
} |
|
153
|
|
|
|
|
154
|
|
|
/** |
|
155
|
|
|
* Generates random image media assets. |
|
156
|
|
|
* |
|
157
|
|
|
* @param int $count |
|
158
|
|
|
* (optional) How many to generate. Defaults to 1. |
|
159
|
|
|
* |
|
160
|
|
|
* @Given a random image |
|
161
|
|
|
* @Given :count random images |
|
162
|
|
|
*/ |
|
163
|
|
|
public function generateRandomImages($count = 1) { |
|
164
|
|
|
$random = new Random(); |
|
165
|
|
|
$entity_type_manager = \Drupal::entityTypeManager(); |
|
166
|
|
|
|
|
167
|
|
|
for ($i = 0; $i < $count; $i++) { |
|
168
|
|
|
$uri = $random->image(uniqid('public://random_') . '.png', '240x240', '640x480'); |
|
|
|
|
|
|
169
|
|
|
|
|
170
|
|
|
/** @var \Drupal\file\FileInterface $file */ |
|
171
|
|
|
$file = $entity_type_manager->getStorage('file')->create(['uri' => $uri]); |
|
172
|
|
|
$file->setMimeType('image/png'); |
|
173
|
|
|
$file->setTemporary(); |
|
174
|
|
|
$file->save(); |
|
175
|
|
|
|
|
176
|
|
|
$media = $entity_type_manager->getStorage('media')->create([ |
|
177
|
|
|
'bundle' => 'image', |
|
178
|
|
|
'name' => $random->name(32), |
|
179
|
|
|
'status' => TRUE, |
|
180
|
|
|
'image' => $file->id(), |
|
181
|
|
|
'field_media_in_library' => TRUE, |
|
182
|
|
|
]); |
|
183
|
|
|
$media->save(); |
|
184
|
|
|
} |
|
185
|
|
|
} |
|
186
|
|
|
|
|
187
|
|
|
/** |
|
188
|
|
|
* Accepts any currently open alert box(es), then optionally runs a callback. |
|
189
|
|
|
* |
|
190
|
|
|
* @param callable $then |
|
191
|
|
|
* (optional) A function to run after accepting the alerts. |
|
192
|
|
|
* @param mixed[] $arguments |
|
193
|
|
|
* (optional) Arguments for the callback. |
|
194
|
|
|
* |
|
195
|
|
|
* @When I accept the alert(s) |
|
196
|
|
|
*/ |
|
197
|
|
|
public function acceptAlerts(callable $then = NULL, array $arguments = []) { |
|
198
|
|
|
$driver = $this->getSession()->getDriver(); |
|
199
|
|
|
if ($driver instanceof Selenium2Driver) { |
|
200
|
|
|
while (true) { |
|
201
|
|
|
try { |
|
202
|
|
|
$driver->getWebDriverSession()->accept_alert(); |
|
203
|
|
|
} |
|
204
|
|
|
catch (NoAlertOpenError $e) { |
|
205
|
|
|
break; |
|
206
|
|
|
} |
|
207
|
|
|
} |
|
208
|
|
|
} |
|
209
|
|
|
if ($then) { |
|
210
|
|
|
call_user_func_array($then, $arguments); |
|
211
|
|
|
} |
|
212
|
|
|
} |
|
213
|
|
|
|
|
214
|
|
|
/** |
|
215
|
|
|
* "Manually" writes text into a field. |
|
216
|
|
|
* |
|
217
|
|
|
* @param string $text |
|
218
|
|
|
* The text to write into the field. |
|
219
|
|
|
* @param string $field |
|
220
|
|
|
* The label, placeholder, ID or name of the field. |
|
221
|
|
|
* |
|
222
|
|
|
* @Given I write :text into :field |
|
223
|
|
|
*/ |
|
224
|
|
|
public function iWriteTextIntoField($text, $field) { |
|
225
|
|
|
$this->getSession() |
|
|
|
|
|
|
226
|
|
|
->getDriver() |
|
227
|
|
|
->getWebDriverSession() |
|
228
|
|
|
->element('xpath', $this->getSession()->getSelectorsHandler()->selectorToXpath('named_exact', array('field', $field))) |
|
229
|
|
|
->postValue(['value' => [$text]]); |
|
230
|
|
|
} |
|
231
|
|
|
|
|
232
|
|
|
/** |
|
233
|
|
|
* Asserts that the current page is an admin page. |
|
234
|
|
|
* |
|
235
|
|
|
* @Then The page should be an admin page |
|
236
|
|
|
*/ |
|
237
|
|
|
public function assertAdminPage() { |
|
238
|
|
|
/** @var \Drupal\Core\Routing\AdminContext $admin_context */ |
|
239
|
|
|
$admin_context = \Drupal::service('router.admin_context'); |
|
240
|
|
|
return $admin_context->isAdminRoute(); |
|
241
|
|
|
} |
|
242
|
|
|
|
|
243
|
|
|
} |
|
244
|
|
|
|
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.