WebDriver and Cookies
WebDriver somewhat deviates away from the ‘only what the user can do’ model when it comes to cookies. Which is amazing since it lets us do a bunch of things outside of the browser (like short-circuiting authentication) since browsers are slow.
According to the JSON Wire Protocol there are three different ways of interacting with cookies
- GET /session/:sessionId/cookie
- POST /session/:sessionId/cookie
- DELETE /session/:sessionId/cookie
In order to illustrate cookie interaction I created a page which will set cookies in a couple different ways, delete them and tell you how many cookies you have set.
These examples are all using PHP via my version of the Facebook bindings. Here is the base script I am using; illustrations will just use specific methods.
<pre lang="php"><?php require_once 'PHPUnit/Framework/TestCase.php';
require_once 'PHPWebDriver/WebDriver.php';
require_once 'PHPWebDriver/WebDriverActionChains.php';
class CookieTest extends PHPUnit_Framework_TestCase {
public function setUp() {
$web_driver = new PHPWebDriver_WebDriver("http://localhost:4444/wd/hub");
$this-?>session = $web_driver->session();
}
public function tearDown() {
$this->session->close();
}
}
How many cookies? – getAllCookies() returns an array so you just count how many there are.
<pre lang="php">/**
* @test
*/
public function no_cookies_on_initial_load() {
$this->session->open("http://element34.ca/cookies/index.php");
$cookies = $this->session->getAllCookies();
$this->assertEquals(count($cookies), 0);
}
Get a specific cookie – getCookie(“name”) will return a single cookie. Notice that $cookie is actually an array itself which is how you check for specific values of things.
<pre lang="php">/**
* @test
*/
public function single_cookie() {
$this->session->open("http://element34.ca/cookies/index.php");
$this->session->element("css selector", 'select[name="colour"] option[value="White"]')->click();
$this->session->element("id", 'single')->submit();
$cookies = $this->session->getAllCookies();
$this->assertEquals(count($cookies), 1);
$cookie = $this->session->getCookie("White");
$this->assertEquals($cookie["value"], 1);
}
Set a cookie – Setting a cookie (setCookie(array)) has a bug right now, but in theory you need to only provide a name (string) and a value (string). Due to the bug however you also provide whether it is secure (boolean). You can also set the path (string), domain (string) and expiry (number).
<pre lang="php">/**
* @test
*/
public function set_cookie() {
// cookie_crumbs: An array, with required keys - "name", "value"
// optional keys - "path", "domain", "expiry", "secure"
$cookie_crumbs = array("name" => "monkey",
"value" => "butt",
"path" => "/",
"secure" => False);
$this->session->open("http://element34.ca/cookies/index.php");
$this->session->setCookie($cookie_crumbs);
$this->session->open("http://element34.ca/cookies/index.php");
$cookies = $this->session->getAllCookies();
$this->assertEquals(count($cookies), 1);
$this->assertEquals($this->session->element("id", 'cookiecount')->text(), "You have 1 cookies set");
}
Delete all cookies – The behavior of deleteAllCookies() makes sense if you recall that WebDriver is talking to the browser, not the server. So you won’t see the cookies having a value of ‘deleted’ and a past timestamp since the browser will have deleted them from itself before we can ping it.
<pre lang="php">/**
* @test
*/
public function deleting_cookies_on_the_client() {
$this->session->open("http://element34.ca/cookies/index.php");
$this->session->element("css selector", 'select[name^="colours"] option[value="Green"]')->click();
$this->session->element("css selector", 'select[name^="colours"] option[value="Yellow"]')->click();
$this->session->element("css selector", 'select[name^="colours"] option[value="Brown"]')->click();
$this->session->element("id", 'multiple')->submit();
$cookies = $this->session->getAllCookies();
$this->assertEquals(count($cookies), 3);
$this->session->deleteAllCookies();
$cookies = $this->session->getAllCookies();
$this->assertEquals(count($cookies), 0);
$this->session->open("http://element34.ca/cookies/index.php");
$this->assertEquals($this->session->element("id", 'cookiecount')->text(), "You have 0 cookies set");
}
Delete a specific cookie – deletCookie(“name”) will delete just that specific cookie
<pre lang="php">/**
* @test
*/
public function deleting_cookie_on_the_client() {
$this->session->open("http://element34.ca/cookies/index.php");
$this->session->element("css selector", 'select[name^="colours"] option[value="Green"]')->click();
$this->session->element("css selector", 'select[name^="colours"] option[value="Yellow"]')->click();
$this->session->element("css selector", 'select[name^="colours"] option[value="Brown"]')->click();
$this->session->element("id", 'multiple')->submit();
$cookies = $this->session->getAllCookies();
$this->assertEquals(count($cookies), 3);
$this->session->deleteCookie("Yellow");
$cookies = $this->session->getAllCookies();
$this->assertEquals(count($cookies), 2);
foreach ($cookies as $cookie) {
$this->assertTrue(in_array($cookie["name"], array("Brown", "Green")));
}
$this->session->open("http://element34.ca/cookies/index.php");
$this->assertEquals($this->session->element("id", 'cookiecount')->text(), "You have 2 cookies set");
}
All the bindings have idiomatic names for their methods, but they are similar enough that converting from one to another shouldn’t be too hard once you know the concepts. I have also made the full class available as a gist if you want to play with it directly.