Passed
Push — develop ( 28c299...928e2a )
by Mathias
12:40
created

Select2Context::fillSearchField()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 9.456
c 0
b 0
f 0
cc 4
nc 4
nop 3
1
<?php
2
/**
3
 * YAWIK
4
 *
5
 * @filesource
6
 * @license MIT
7
 * @copyright  2013 - 2017 Cross Solution <http://cross-solution.de>
8
 */
9
10
namespace Yawik\Behat;
11
12
13
use Behat\Behat\Context\Context;
14
use Behat\Mink\Element\DocumentElement;
15
use Behat\MinkExtension\Context\RawMinkContext;
16
use WebDriver\Element;
17
18
/**
19
 * Class Select2Context
20
 *
21
 * @author Anthonius Munthi <[email protected]>
22
 * @package Yawik\Behat
23
 * @since 0.29
24
 */
25
class Select2Context extends RawMinkContext implements Context
26
{
27
	protected $timeout = 5;
28
	
29
	/**
30
	 * Fills in Select2 field with specified
31
	 *
32
	 * @When /^(?:|I )fill in select2 "(?P<field>(?:[^"]|\\")*)" with "(?P<value>(?:[^"]|\\")*)"$/
33
	 * @When /^(?:|I )fill in select2 "(?P<value>(?:[^"]|\\")*)" for "(?P<field>(?:[^"]|\\")*)"$/
34
	 */
35
	public function iFillInSelect2Field($field, $value)
36
	{
37
		$page = $this->getSession()->getPage();
38
		
39
		$this->openField($page, $field);
40
		$this->selectValue($page, $field, $value, $this->timeout);
41
	}
42
	
43
	/**
44
	 * @When I fill in select2 search :field with :search and I choose :choice
45
	 * @param $field
46
	 * @param $value
47
	 */
48
	public function iFillInSelect2FieldWith($field,$search,$choice=null)
49
	{
50
		$page = $this->getSession()->getPage();
51
		$this->openField($page, $field);
52
		$this->fillSearchField($page,$field,$search);
53
		$this->selectValue($page, $field, $choice);
54
	}
55
	
56
	/**
57
	 * Fill Select2 search field
58
	 *
59
	 * @param DocumentElement $page
60
	 * @param string          $field
61
	 * @param string          $value
62
	 * @throws \Exception
63
	 */
64
	private function fillSearchField(DocumentElement $page, $field, $value)
65
	{
66
		$driver = $this->getSession()->getDriver();
67
		if ('Behat\Mink\Driver\Selenium2Driver' === get_class($driver)) {
68
			// Can't use `$this->getSession()->getPage()->find()` because of https://github.com/minkphp/MinkSelenium2Driver/issues/188
69
			
70
			$element = $page->find('css','.select2-container--open .select2-search__field');
71
			$xpath = $element->getXpath();
72
			$select2Input = $this->getSession()
73
				->getDriver()
74
				->getWebDriverSession()
75
				->element('xpath',$xpath)
76
				//->element('xpath', "//html/descendant-or-self::*[@class and contains(concat(' ', normalize-space(@class), ' '), ' select2-search__field ')]")
77
			;
78
			if (!$select2Input) {
79
				throw new \Exception(sprintf('No field "%s" found', $field));
80
			}
81
			
82
			$select2Input->postValue(['value' => [$value]]);
83
		} else {
84
			$select2Input = $page->find('css', '.select2-search__field');
85
			if (!$select2Input) {
86
				throw new \Exception(sprintf('No input found for "%s"', $field));
87
			}
88
			$select2Input->setValue($value);
89
		}
90
		
91
		$this->waitForLoadingResults($this->timeout);
92
	}
93
	
94
	/**
95
	 * Select value in choice list
96
	 *
97
	 * @param DocumentElement $page
98
	 * @param string          $field
99
	 * @param string          $value
100
	 * @param int             $time
101
	 * @throws \Exception
102
	 */
103
	private function selectValue(DocumentElement $page, $field, $value, $time=5)
104
	{
105
		$this->waitForLoadingResults($time);
106
		
107
		$chosenResults = $page->findAll('css', '.select2-results li');
108
		foreach ($chosenResults as $result) {
109
			$text = $result->getText();
110
			if (false!==strpos($text,$value)) {
111
				$result->click();
112
				return;
113
			}
114
		}
115
		
116
		throw new \Exception(sprintf('Value "%s" not found for "%s"', $value, $field));
117
	}
118
	
119
	private function openField(DocumentElement $page, $field)
120
	{
121
		$inputField = $page->find('css',$field);
122
		if(!$inputField){
123
			$fieldName = sprintf('select[name="%s"] + .select2-container', $field);
124
			$inputField = $page->find('css', $fieldName);
125
		}
126
		if (!$inputField) {
127
			throw new \Exception(sprintf('No field "%s" found', $field));
128
		}
129
		
130
		$choice = $inputField->find('css', '.select2-selection');
131
		if (!$choice) {
132
			throw new \Exception(sprintf('No select2 choice found for "%s"', $field));
133
		}
134
		$choice->press();
135
	}
136
	
137
	/**
138
	 * Wait the end of fetching Select2 results
139
	 *
140
	 * @param int $time Time to wait in seconds
141
	 */
142
	private function waitForLoadingResults($time)
143
	{
144
		for ($i = 0; $i < $time; $i++) {
145
			if (!$this->getSession()->getPage()->find('css', '.select2-results__option.loading-results')) {
146
				return;
147
			}
148
			
149
			sleep(1);
150
		}
151
	}
152
	
153
}