forked from roquie/laravel-dusk-select2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmacro.php
74 lines (61 loc) · 2.7 KB
/
macro.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<?php
declare(strict_types=1);
use Laravel\Dusk\Browser;
use Facebook\WebDriver\Exception\{
ElementNotInteractableException,
WebDriverException,
ElementNotVisibleException
};
/**
* Register simple macros for the Laravel Dusk.
* $field - selector, or @element
* $value - option value, may be multiple, eg. ['foo', 'bar']
* $wait - maximum count of seconds for ajax loading.
*/
Browser::macro('select2', function ($field, $value = null, $wait = 2, $suffix = ' + .select2') {
/** @var Browser $this */
$selector = $field.$suffix;
$element = $this->element($selector);
if (!$element && !$element->isDisplayed()) {
throw new InvalidArgumentException("Selector [$selector] not found or not displayed.");
}
$highlightedClass = '.select2-results__option--highlighted';
$highlightedSelector = '.select2-results__options ' . $highlightedClass;
$selectableSelector = '.select2-results__options .select2-results__option';
$searchSelector = '.select2-container.select2-container--open .select2-search__field';
$this->click($selector);
// if $value equal null, find random element and click him.
// @todo: may be a couple of times move scroll to down (ajax paging)
if (null === $value) {
$this->waitFor($highlightedSelector, $wait);
$this->script(implode('', [
"var _dusk_s2_elements = document.querySelectorAll('$selectableSelector');",
"document.querySelector('$highlightedSelector').classList.remove('$highlightedClass');",
'var _dusk_s2_el = _dusk_s2_elements[Math.floor(Math.random()*(_dusk_s2_elements.length - 1))];',
"_dusk_s2_el.classList.add('$highlightedClass');"
]));
$this->click($highlightedSelector);
return $this;
}
// check if search field exists and fill it.
$element = $this->element($searchSelector);
if ($element->isDisplayed()) {
try {
foreach ((array) $value as $item) {
$element->sendKeys($item);
$this->waitFor($highlightedSelector, $wait);
$this->click($highlightedSelector);
}
return $this;
} catch (WebDriverException $exception) {
if (!$exception instanceof ElementNotInteractableException || !$exception instanceof ElementNotVisibleException) {
throw $exception;
}
// ... otherwise ignore the exception and try another way
}
}
// another way - w/o search field.
$field = str_replace('\\', '\\\\', $field);
$this->script("jQuery(\"$field\").val((function () { return jQuery(\"$field option:contains('$value')\").val(); })()).trigger('change')");
return $this;
});