Skip to content

Commit 283e4d0

Browse files
committed
createSession method implementation for W3C client
1 parent 1045e5c commit 283e4d0

4 files changed

Lines changed: 76 additions & 5 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ See a self-documented [ClientInterface.php](src/ClientInterface.php) for the API
3535
## See also
3636

3737
- [php-webdriver/webdriver](https://github.com/php-webdriver/php-webdriver) — the original, "blocking" implementation;
38-
to get information how to use some advanced methods, for example, [WebDriverKeys](https://github.com/php-webdriver/php-webdriver/blob/main/lib/WebDriverKeys.php#L10)
39-
helper describes Unicode strings for sending special inputs to page elements (e.g. `Ctrl`, `Alt`, etc.).
38+
to get information how to use some advanced methods. For example, [WebDriverKeys](https://github.com/php-webdriver/php-webdriver/blob/main/lib/WebDriverKeys.php#L10)
39+
helper describes Unicode strings for sending special inputs to page elements (e.g. `Ctrl`, `Alt` and other keys).
4040

4141
## Changelog
4242

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"php": ">=7.4",
2626
"react/http": "^1.1",
2727
"react/promise": "^2.8",
28+
"react/promise-timer": "^1.6",
2829
"symfony/options-resolver": "^5.1"
2930
},
3031
"require-dev": {

src/Client/W3CClient.php

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@
1616
namespace Itnelo\React\WebDriver\Client;
1717

1818
use Itnelo\React\WebDriver\ClientInterface;
19+
use Psr\Http\Message\ResponseInterface;
1920
use React\Http\Browser;
21+
use React\Promise\Deferred;
2022
use React\Promise\PromiseInterface;
23+
use RuntimeException;
2124
use Symfony\Component\OptionsResolver\Exception\ExceptionInterface as OptionsResolverExceptionInterface;
2225
use Symfony\Component\OptionsResolver\OptionsResolver;
26+
use Throwable;
2327

2428
/**
2529
* W3C compliant WebDriver client for Selenium Grid server (hub) that performs asynchronously.
@@ -129,15 +133,66 @@ function (OptionsResolver $requestOptionsResolver) {
129133
*/
130134
public function getSessionIdentifiers(): PromiseInterface
131135
{
132-
// TODO: Implement getSessionIdentifiers() method.
136+
// todo
133137
}
134138

135139
/**
136140
* {@inheritDoc}
137141
*/
138142
public function createSession(): PromiseInterface
139143
{
140-
// TODO: Implement createSession() method.
144+
$sessionOpeningDeferred = new Deferred();
145+
146+
$requestUri = sprintf(
147+
'http://%s:%d/wd/hub/session',
148+
$this->_options['server']['host'],
149+
$this->_options['server']['port']
150+
);
151+
152+
$requestHeaders = [
153+
'Content-Type' => 'application/json; charset=UTF-8',
154+
];
155+
156+
// todo: implement custom executable args / prefs support (omitted in the interface)
157+
$requestContents = '{"capabilities":{"firstMatch":[{"browserName":"chrome","goog:chromeOptions":{"prefs":{"intl.accept_languages":"RU-ru,ru,en-US,en"},"args":["--user-data-dir=\/opt\/google\/chrome\/profiles"]}}]},"desiredCapabilities":{"browserName":"chrome","platform":"ANY","goog:chromeOptions":{"prefs":{"intl.accept_languages":"RU-ru,ru,en-US,en"},"args":["--user-data-dir=\/opt\/google\/chrome\/profiles"]}}}';
158+
159+
$responsePromise = $this->httpClient->post($requestUri, $requestHeaders, $requestContents);
160+
161+
$responsePromise->then(
162+
function (ResponseInterface $response) use ($sessionOpeningDeferred) {
163+
try {
164+
$responseBody = (string) $response->getBody();
165+
preg_match('/sessionid[":\s]+([a-z\d]{32})/Ui', $responseBody, $matches);
166+
167+
if (!isset($matches[1])) {
168+
// todo: locate an error message or set it as "undefined error".
169+
throw new RuntimeException('Unable to locate session identifier in the response.');
170+
}
171+
172+
$sessionIdentifier = $matches[1];
173+
$sessionOpeningDeferred->resolve($sessionIdentifier);
174+
} catch (Throwable $exception) {
175+
$reason = new RuntimeException(
176+
'Unable to open a selenium hub session (response deserialization).',
177+
0,
178+
$exception
179+
);
180+
181+
$sessionOpeningDeferred->reject($reason);
182+
}
183+
},
184+
function (Throwable $rejectionReason) use ($sessionOpeningDeferred) {
185+
$reason = new RuntimeException('Unable to open a selenium hub session (request).', 0, $rejectionReason);
186+
187+
$sessionOpeningDeferred->reject($reason);
188+
}
189+
);
190+
191+
$sessionIdentifierPromise = $sessionOpeningDeferred->promise();
192+
193+
// todo: apply timeout
194+
195+
return $sessionIdentifierPromise;
141196
}
142197

143198
/**

src/ClientInterface.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,22 @@ public function getSessionIdentifiers(): PromiseInterface;
3838

3939
/**
4040
* Returns a promise that resolves to a string, representing identifier of session that has been started by the
41-
* remote WebDriver service
41+
* remote WebDriver service.
42+
*
43+
* Usage example:
44+
*
45+
* ```
46+
* $sessionIdentifierPromise = $webdriver->createSession();
47+
*
48+
* $sessionIdentifierPromise->then(
49+
* function (string $sessionIdentifier) {
50+
* // do some work
51+
* },
52+
* function (Throwable $rejectionReason) {
53+
* // handle exception
54+
* }
55+
* );
56+
* ```
4257
*
4358
* todo: argument to send desired capabilities, i.e. browser arguments and preferences (omitted)
4459
* todo: must also return a collection of confirmed browser capabilities (omitted)

0 commit comments

Comments
 (0)