Completed
Push — master ( 200256...2dbcc8 )
by Haralan
02:22
created

Driver_Selenium_Connection::call()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 32
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 4

Importance

Changes 4
Bugs 0 Features 2
Metric Value
c 4
b 0
f 2
dl 0
loc 32
ccs 19
cts 19
cp 1
rs 8.5806
cc 4
eloc 20
nc 4
nop 2
crap 4
1
<?php
2
3
namespace Openbuildings\Spiderling;
4
5
/**
6
 * Connect to selenium service.
7
 * Send requests to selenium
8
 *
9
 * @package    Openbuildings\Spiderling
10
 * @author     Ivan Kerin
11
 * @copyright  (c) 2013 OpenBuildings Ltd.
12
 * @license    http://spdx.org/licenses/BSD-3-Clause
13
 */
14
class Driver_Selenium_Connection
15
{
16
	/**
17
	 * The current selenium session id
18
	 * @var string
19
	 */
20
	protected $_session_id;
21
22
	/**
23
	 * The selenium server url
24
	 * @var string
25
	 */
26
	protected $_server = 'http://localhost:4444/wd/hub/';
27
28 13
	public function server($server = NULL)
29
	{
30 13
		if ($server !== NULL)
31 13
		{
32 1
			$this->_server = $server;
33 1
			return $this;
34
		}
35 13
		return $this->_server;
36
	}
37
38 2
	public function __construct($server = NULL)
39
	{
40
		if ($server)
41 2
		{
42 1
			$this->server($server);
43 1
		}
44 2
	}
45
46
	/**
47
	 * Start a new selenium session, based on passed desired capabilities.
48
	 * Reuses the session if possible
49
	 *
50
	 * @param  array $desiredCapabilities
51
	 */
52 2
	public function start(array $desiredCapabilities = NULL)
53
	{
54 2
		if ( ! ($this->_session_id = $this->reuse_session()))
55 2
		{
56 1
			$this->_session_id = $this->new_session($desiredCapabilities);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->new_session($desiredCapabilities) of type object<Openbuildings\Spiderling\new> is incompatible with the declared type string of property $_session_id.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
57 1
		}
58
59 2
		$this->_server .= "session/{$this->_session_id}/";
60 2
	}
61
62
	/**
63
	 * Check if a session has been started
64
	 * @return boolean
65
	 */
66 2
	public function is_started()
67
	{
68 2
		return (bool) $this->_session_id;
69
	}
70
71
	/**
72
	 * Try to reuse an existing selenium session, return the reused id
73
	 * @return string
74
	 */
75 2
	public function reuse_session()
76
	{
77 2
		$sessions = $this->get('sessions');
78 2
		foreach ($sessions as $session)
79
		{
80 2
			$id = $session['id'];
81
			try
82
			{
83 2
				$this->get("session/$id/window_handle");
84 2
				return $id;
85
			}
86
			// @codeCoverageIgnoreStart
87
			// This cannot be tested because of selenium bug (can't close main window)
88
			catch (Exception_Selenium $exception)
89
			{
90
				$this->delete("session/$id");
91
			}
92
			// @codeCoverageIgnoreEnd
93 1
		}
94 1
	}
95
96
	/**
97
	 * Initiate a new session, based on the desired capabilities
98
	 * @param  array $desiredCapabilities
99
	 * @return new session
100
	 */
101 1
	public function new_session(array $desiredCapabilities = NULL)
102
	{
103 1
		if ( ! $desiredCapabilities)
104 1
		{
105 1
			$desiredCapabilities = array('browserName' => 'firefox');
106 1
		}
107
108 1
		$session = $this->post('session', array('desiredCapabilities' => $desiredCapabilities));
109 1
		return $session['webdriver.remote.sessionid'];
110
	}
111
112
	/**
113
	 * Perform a get request to the selenium server
114
	 * @param  string $command
115
	 * @return mixed
116
	 */
117 12
	public function get($command)
118
	{
119 12
		return $this->call($command);
120
	}
121
122
	/**
123
	 * Perform a post request to the selenium server
124
	 * @param  string $command
125
	 * @param  array  $params
126
	 * @return mixed
127
	 */
128 10
	public function post($command, array $params)
129
	{
130 10
		$options = array();
131 10
		$options[CURLOPT_POST] = TRUE;
132
133 10
		if ($params) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $params of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
134 10
			$options[CURLOPT_POSTFIELDS] = json_encode($params);
135 10
		}
136
137 10
		return $this->call($command, $options);
138
	}
139
140
	/**
141
	 * Perform a delete request to the selenium server
142
	 * @param  string $command
143
	 * @return mixed
144
	 */
145 1
	public function delete($command)
146
	{
147 1
		$options = array();
148 1
		$options[CURLOPT_CUSTOMREQUEST] = 'DELETE';
149
150 1
		return $this->call($command, $options);
151
	}
152
153
	/**
154
	 * Perform a request to the selenium server, using curl
155
	 * @param  string $command
156
	 * @param  array  $options curl options
157
	 * @return mixed
158
	 */
159 13
	public function call($command, array $options = array())
160
	{
161 13
		$curl = curl_init();
162 13
		$options[CURLOPT_URL] = $this->server().$command;
163 13
		$options[CURLOPT_RETURNTRANSFER] = TRUE;
164 13
		$options[CURLOPT_FOLLOWLOCATION] = TRUE;
165 13
		$options[CURLOPT_HTTPHEADER] = array(
166 13
			'Content-Type: application/json;charset=UTF-8',
167 13
			'Accept: application/json',
168
		);
169
170 13
		curl_setopt_array($curl, $options);
171
172 13
		$raw = trim(curl_exec($curl));
173
174 13
		$result = json_decode($raw, TRUE);
175
176 13
		$error = curl_error($curl);
177
178 13
		curl_close($curl);
179
180
		if ($error)
181 13
			throw new Exception_Driver('Curl ":command" throws exception :error', array(':command' => $command, ':error' => $error));
182
183 13
		if ($result['status'] == 10)
184 13
			throw new Exception_Staleelement();
185
186 13
		if ($result['status'] != 0)
187 13
			throw new Exception_Selenium($result['status']);
188
189 13
		return $result['value'];
190
	}
191
}
192