FormContext::checkboxAction()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 8
ccs 0
cts 6
cp 0
rs 9.4285
cc 2
eloc 4
nc 2
nop 2
crap 6
1
<?php
2
/**
3
 * @author Sergii Bondarenko, <[email protected]>
4
 */
5
namespace Drupal\TqExtension\Context\Form;
6
7
// Exceptions.
8
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
9
use Behat\Mink\Exception\ElementNotFoundException;
10
use WebDriver\Exception\NoSuchElement;
11
// Helpers.
12
use Behat\Gherkin\Node\TableNode;
13
use WebDriver\Service\CurlService;
14
use Behat\Mink\Element\NodeElement;
15
// Utils.
16
use Drupal\TqExtension\Utils\DatePicker;
17
use Drupal\TqExtension\Utils\FormValueAssertion;
18
use Drupal\TqExtension\Utils\EntityDrupalWrapper;
19
20
class FormContext extends RawFormContext
21
{
22
    /**
23
     * @param string $value
24
     *   Typed text.
25
     * @param string $selector
26
     *   Selector of the field.
27
     * @param int $option
28
     *   An option number. Will be selected from loaded variants.
29
     *
30
     * @throws \InvalidArgumentException
31
     *   When $option is less than zero.
32
     * @throws NoSuchElement
33
     *   When autocomplete list was not loaded.
34
     * @throws \RuntimeException
35
     *   When neither option was not loaded.
36
     * @throws \OverflowException
37
     *   When $option is more than variants are available.
38
     * @throws \Exception
39
     *   When value was not changed.
40
     *
41
     * @Then /^(?:|I )typed "([^"]*)" in the "([^"]*)" field and chose (\d+) option from autocomplete variants$/
42
     */
43
    public function choseOptionFromAutocompleteVariants($value, $selector, $option)
44
    {
45
        if (!$option) {
46
            throw new \InvalidArgumentException(sprintf(
47
                'An option that will be chosen expected as positive number, but was got the: %s',
48
                $option
49
            ));
50
        }
51
52
        $field = $this->element('field', $selector);
53
        // Syn - a Standalone Synthetic Event Library, provided by Selenium.
54
        $this->executeJsOnElement($field, sprintf("Syn.type({{ELEMENT}}, '%s')", token_replace($value)));
55
        $this->waitAjaxAndAnimations();
56
57
        $autocomplete = $field->getParent()->findById('autocomplete');
58
        $this->throwNoSuchElementException('#autocomplete', $autocomplete);
59
60
        $options = count($autocomplete->findAll('css', 'li'));
61
62
        if ($options < 1) {
63
            throw new \RuntimeException('Neither option was not loaded.');
64
        }
65
66
        if ($option > $options) {
67
            throw new \OverflowException(sprintf(
68
                'You can not select an option %s, as there are only %d.',
69
                $option,
70
                $options
71
            ));
72
        }
73
74
        for ($i = 0; $i < $option; $i++) {
75
            // 40 - down
76
            $field->keyDown(40);
77
            $field->keyUp(40);
78
        }
79
80
        // 13 - return
81
        $field->keyDown(13);
82
        $field->keyUp(13);
83
84
        if ($field->getValue() == $value) {
85
            throw new \Exception(sprintf('The value of "%s" field was not changed.', $selector));
86
        }
87
    }
88
89
    /**
90
     * Use the current user data for filling fields.
91
     *
92
     * @example
93
     * Then I fill "First name" with value of field "First name" of current user
94
     * And fill "field_last_name[und][0]" with value of field "field_user_last_name" of current user
95
     *
96
     * @param string $field
97
     *   The name of field to fill in. HTML Label, name or ID can be user as selector.
98
     * @param string $user_field
99
     *   The name of field from which the data will taken. Drupal label or machine name can be used as selector.
100
     *
101
     * @throws \InvalidArgumentException
102
     * @throws \UnexpectedValueException
103
     * @throws \Exception
104
     * @throws NoSuchElement
105
     *   When field cannot be found.
106
     *
107
     * @Then /^(?:I )fill "([^"]*)" with value of field "([^"]*)" of current user$/
108
     */
109
    public function fillInWithValueOfFieldOfCurrentUser($field, $user_field)
110
    {
111
        if (!empty($this->user) && !$this->user->uid) {
0 ignored issues
show
Documentation introduced by
The property user does not exist on object<Drupal\TqExtensio...ntext\Form\FormContext>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
112
            throw new \Exception('Anonymous user have no fields');
113
        }
114
115
        $entity = new EntityDrupalWrapper('user');
116
        $wrapper = $entity->wrapper($this->user->uid);
0 ignored issues
show
Documentation introduced by
The property user does not exist on object<Drupal\TqExtensio...ntext\Form\FormContext>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
117
        $user_field = $entity->getFieldNameByLocator($user_field);
118
119
        if (empty($wrapper->{$user_field})) {
120
            throw new \InvalidArgumentException(sprintf('User entity has no "%s" field.', $user_field));
121
        }
122
123
        $value = $wrapper->{$user_field}->value();
124
125
        if (empty($value)) {
126
            throw new \UnexpectedValueException('The value of "%s" field is empty.', $user_field);
127
        }
128
129
        $this->fillField($field, $value);
130
    }
131
132
    /**
133
     * @param string $action
134
     *   Can be "check" or "uncheck".
135
     * @param TableNode $checkboxes
136
     *   Table with one row of checkboxes selectors.
137
     *
138
     * @example
139
     * I uncheck the boxes:
140
     *   | Consumer Products  |
141
     *   | Financial Services |
142
     *
143
     * @example
144
     * I check the boxes:
145
     *   | Consumer Products  |
146
     *   | Financial Services |
147
     *
148
     * @Given /^(?:|I )(?:|un)check the boxes:/
149
     */
150
    public function checkboxAction($action, TableNode $checkboxes)
151
    {
152
        $minkContext = $this->getMinkContext();
153
154
        foreach ($checkboxes->getRows() as $checkbox) {
155
            $minkContext->{trim($action) . 'Option'}(reset($checkbox));
156
        }
157
    }
158
159
    /**
160
     * This method was defined and used instead of "assertSelectRadioById",
161
     * because the field label can contain too long value and better to use
162
     * another selector instead of label.
163
     *
164
     * @see MinkContext::assertSelectRadioById()
165
     *
166
     * @param string $customized
167
     *   Can be an empty string or " customized".
168
     * @param string $selector
169
     *   Field selector.
170
     *
171
     * @throws NoSuchElement
172
     *   When radio button was not found.
173
     * @throws \Exception
174
     *
175
     * @Given /^(?:|I )check the(| customized) "([^"]*)" radio button$/
176
     */
177
    public function radioAction($customized, $selector)
178
    {
179
        $field = $this->getWorkingElement()->findField($selector);
180
        $customized = (bool) $customized;
181
182
        if ($field !== null && !$customized) {
183
            $field->selectOption($field->getAttribute('value'));
184
            return;
185
        }
186
187
        // Find all labels of a radio button or only first, if it is not custom.
188
        foreach ($this->findLabels($selector) as $label) {
189
            // Check a custom label for visibility.
190
            if ($customized && !$label->isVisible()) {
191
                continue;
192
            }
193
194
            $label->click();
195
            return;
196
        }
197
198
        $this->throwNoSuchElementException($selector, $field);
199
    }
200
201
    /**
202
     * @param string $selector
203
     * @param string $value
204
     *
205
     * @throws NoSuchElement
206
     *
207
     * @When /^(?:|I )fill "([^"]*)" with "([^"]*)"$/
208
     */
209
    public function fillField($selector, $value)
210
    {
211
        $this->element('field', $selector)->setValue(token_replace($value));
212
    }
213
214
    /**
215
     * @param TableNode $fields
216
     *   | Field locator | Value |
217
     *
218
     * @throws NoSuchElement
219
     *
220
     * @When /^(?:|I )fill the following:$/
221
     */
222
    public function fillFields(TableNode $fields)
223
    {
224
        foreach ($fields->getRowsHash() as $field => $value) {
225
            $this->fillField($field, $value);
226
        }
227
    }
228
229
    /**
230
     * @param string $file
231
     *   Path to a file. Relative to the directory specified in "files_path" in behat.yml.
232
     * @param string $selector
233
     *   Field selector (label|id|name).
234
     *
235
     * @throws \Exception
236
     * @throws NoSuchElement
237
     *
238
     * @Given /^(?:|I )attach file "([^"]*)" to "([^"]*)"$/
239
     */
240
    public function attachFile($file, $selector)
241
    {
242
        $filesPath = $this->getMinkParameter('files_path');
243
244
        if (!$filesPath) {
245
            throw new \Exception('The "files_path" Mink parameter was not configured.');
246
        }
247
248
        $file = rtrim(realpath($filesPath), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $file;
249
250
        if (!is_file($file)) {
251
            throw new \InvalidArgumentException(sprintf('The "%s" file does not exist.', $file));
252
        }
253
254
        $this->element('field', $selector)->attachFile($file);
255
    }
256
257
    /**
258
     * @param string $selector
259
     * @param TableNode $values
260
     *
261
     * @throws ElementNotFoundException
262
     * @throws \Exception
263
     * @throws NoSuchElement
264
     *
265
     * @Given /^(?:|I )select the following in "([^"]*)" hierarchical select:$/
266
     */
267
    public function setValueForHierarchicalSelect($selector, TableNode $values)
268
    {
269
        $element = $this->getWorkingElement();
270
        // Try to selects by wrapper ID.
271
        $wrapper = $element->findById($selector);
272
273
        if (null !== $wrapper) {
274
            $labels = $wrapper->findAll('xpath', '//label[@for]');
275
        } else {
276
            $labels = $this->findLabels($selector);
277
        }
278
279
        if (empty($labels)) {
280
            throw new \Exception('No one hierarchical select was found.');
281
        }
282
283
        /** @var NodeElement $label */
284
        $label = reset($labels);
285
        $parent = $label->getParent();
286
287
        foreach (array_keys($values->getRowsHash()) as $i => $value) {
288
            /** @var NodeElement[] $selects */
289
            $selects = [];
290
291
            /** @var NodeElement $select */
292
            foreach ($parent->findAll('css', 'select') as $select) {
293
                if ($select->isVisible()) {
294
                    $selects[] = $select;
295
                }
296
            }
297
298
            if (!isset($selects[$i])) {
299
                throw new \InvalidArgumentException(sprintf(
300
                    'The value "%s" was specified for select "%s" but it does not exist.',
301
                    $value,
302
                    $i
303
                ));
304
            }
305
306
            $selects[$i]->selectOption($value);
307
            $this->waitAjaxAndAnimations();
308
        }
309
    }
310
311
    /**
312
     * Check that an image was uploaded and can be viewed on the page.
313
     *
314
     * @throws \Exception
315
     * @throws FileNotFoundException
316
     *
317
     * @Then /^(?:|I )should see the thumbnail$/
318
     */
319
    public function shouldSeeThumbnail()
320
    {
321
        $thumb = false;
322
323
        foreach (['.upload-preview', '.media-thumbnail img', '.image-preview img'] as $selector) {
324
            if ($thumb) {
325
                break;
326
            }
327
328
            $thumb = $this->findByCss($selector);
329
        }
330
331
        if (null === $thumb) {
332
            throw new \Exception('An expected image tag was not found.');
333
        }
334
335
        $file = explode('?', $thumb->getAttribute('src'));
336
        $file = reset($file);
337
338
        $curl = new CurlService();
339
        list(, $info) = $curl->execute('GET', $file);
340
341
        if (empty($info) || strpos($info['content_type'], 'image/') === false) {
342
            throw new FileNotFoundException(sprintf('%s did not return an image', $file));
343
        }
344
    }
345
346
    /**
347
     * @param string $option
348
     * @param string $selector
349
     *
350
     * @Then /^(?:|I )pick "([^"]*)" from "([^"]*)"$/
351
     */
352
    public function selectFrom($option, $selector)
353
    {
354
        $this->element('*', $selector)->selectOption($option);
355
    }
356
357
    /**
358
     * @example
359
     * And pick the following:
360
     *   | Entity Reference                     | Type of new field    |
361
     *   | Inline entity form - Multiple values | Widget for new field |
362
     *
363
     * @param TableNode $rows
364
     *
365
     * @Then /^(?:|I )pick the following:$/
366
     */
367
    public function selectFromFollowing(TableNode $rows)
368
    {
369
        foreach ($rows->getRowsHash() as $option => $selector) {
370
            $this->selectFrom($option, $selector);
371
        }
372
    }
373
374
    /**
375
     * @example
376
     * And check that "Users" field has "admin" value
377
     * And check that "Users" field has not "customer" value
378
     *
379
     * @Then /^(?:|I )check that "([^"]*)" field has(| not) "([^"]*)" value$/
380
     */
381
    public function assertTextualField($selector, $not, $expected)
382
    {
383
        (new FormValueAssertion($this, $selector, $not, $expected))->textual();
384
    }
385
386
    /**
387
     * @example
388
     * And check that "User" is selected in "Apply to" select
389
     * And check that "Product(s)" is not selected in "Apply to" select
390
     *
391
     * @Then /^(?:|I )check that "([^"]*)" is(| not) selected in "([^"]*)" select$/
392
     */
393
    public function assertSelectableField($expected, $not, $selector)
394
    {
395
        (new FormValueAssertion($this, $selector, $not, $expected))->selectable();
396
    }
397
398
    /**
399
     * @example
400
     * And check that "Order discount" is checked
401
     * And check that "Product discount" is not checked
402
     *
403
     * @Then /^(?:|I )check that "([^"]*)" is(| not) checked$/
404
     */
405
    public function assertCheckableField($selector, $not)
406
    {
407
        (new FormValueAssertion($this, $selector, $not))->checkable();
408
    }
409
410
    /**
411
     * @param string $date
412
     * @param string $selector
413
     *
414
     * @Then /^(?:|I )choose "([^"]*)" in "([^"]*)" datepicker$/
415
     * @Then /^(?:|I )set the "([^"]*)" for "([^"]*)" datepicker$/
416
     */
417
    public function setDate($date, $selector)
418
    {
419
        (new DatePicker($this, $selector, $date))->isDateAvailable()->setDate()->isDateSelected();
420
    }
421
422
    /**
423
     * @param string $selector
424
     * @param string $date
425
     *
426
     * @Then /^(?:|I )check that "([^"]*)" datepicker contains "([^"]*)" date$/
427
     */
428
    public function isDateSelected($selector, $date)
429
    {
430
        (new DatePicker($this, $selector, $date))->isDateSelected();
431
    }
432
433
    /**
434
     * @param string $date
435
     * @param string $selector
436
     *
437
     * @Then /^(?:|I )check that "([^"]*)" is available for "([^"]*)" datepicker$/
438
     */
439
    public function isDateAvailable($date, $selector)
440
    {
441
        (new DatePicker($this, $selector, $date))->isDateAvailable();
442
    }
443
}
444