Implemnts the commands in webdriver to preform searching of elements on a page.
/session/:sessionId/timeouts/implicit_wait /session/:sessionId/element /session/:sessionId/elements /session/:sessionId/element/:id/element /session/:sessionId/element/:id/elements BUG=none TEST=webdriver_remote_tests.py Review URL: http://codereview.chromium.org/3643002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70107 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@@ -685,6 +685,10 @@
|
|||||||
'test/webdriver/commands/command.cc',
|
'test/webdriver/commands/command.cc',
|
||||||
'test/webdriver/commands/create_session.h',
|
'test/webdriver/commands/create_session.h',
|
||||||
'test/webdriver/commands/create_session.cc',
|
'test/webdriver/commands/create_session.cc',
|
||||||
|
'test/webdriver/commands/find_element_commands.h',
|
||||||
|
'test/webdriver/commands/find_element_commands.cc',
|
||||||
|
'test/webdriver/commands/implicit_wait_command.h',
|
||||||
|
'test/webdriver/commands/implicit_wait_command.cc',
|
||||||
'test/webdriver/commands/execute_command.h',
|
'test/webdriver/commands/execute_command.h',
|
||||||
'test/webdriver/commands/execute_command.cc',
|
'test/webdriver/commands/execute_command.cc',
|
||||||
'test/webdriver/commands/navigate_commands.h',
|
'test/webdriver/commands/navigate_commands.h',
|
||||||
|
111
chrome/test/webdriver/commands/find_element_commands.cc
Normal file
111
chrome/test/webdriver/commands/find_element_commands.cc
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "chrome/test/webdriver/commands/find_element_commands.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "base/string_number_conversions.h"
|
||||||
|
#include "base/utf_string_conversions.h"
|
||||||
|
#include "base/values.h"
|
||||||
|
#include "third_party/webdriver/atoms.h"
|
||||||
|
#include "chrome/test/webdriver/error_codes.h"
|
||||||
|
#include "chrome/test/webdriver/utility_functions.h"
|
||||||
|
|
||||||
|
namespace webdriver {
|
||||||
|
|
||||||
|
bool FindElementCommand::Init(Response* const response) {
|
||||||
|
if (!WebDriverCommand::Init(response)) {
|
||||||
|
SET_WEBDRIVER_ERROR(response, "Failure on Init for find element",
|
||||||
|
kInternalServerError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetStringASCIIParameter("using", &use_) ||
|
||||||
|
!GetStringASCIIParameter("value", &value_)) {
|
||||||
|
SET_WEBDRIVER_ERROR(response,
|
||||||
|
"Request is missing required 'using' and/or 'value' data", kBadRequest);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jmikhail): The findElement(s) atom should handle this conversion.
|
||||||
|
if ("class name" == use_) {
|
||||||
|
use_ = "className";
|
||||||
|
} else if ("link text" == use_) {
|
||||||
|
use_ = "linkText";
|
||||||
|
} else if ("partial link text" == use_) {
|
||||||
|
use_ = "partialLinkText";
|
||||||
|
} else if ("tag name" == use_) {
|
||||||
|
use_ = "tagName";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Searching under a custom root if the URL pattern is
|
||||||
|
// "/session/$session/element/$id/element(s)"
|
||||||
|
root_element_id_ = GetPathVariable(4);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindElementCommand::ExecutePost(Response* const response) {
|
||||||
|
scoped_ptr<ListValue> args(new ListValue());
|
||||||
|
DictionaryValue* locator = new DictionaryValue();
|
||||||
|
ErrorCode error;
|
||||||
|
std::wstring jscript;
|
||||||
|
Value* result = NULL;
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
// Set the command we are using to locate the value beging searched for.
|
||||||
|
locator->SetString(use_, value_);
|
||||||
|
args->Append(locator);
|
||||||
|
args->Append(root_element_id_.size() == 0 ? Value::CreateNullValue() :
|
||||||
|
WebDriverCommand::GetElementIdAsDictionaryValue(root_element_id_));
|
||||||
|
if (find_one_element_) {
|
||||||
|
jscript = build_atom(FIND_ELEMENT, sizeof FIND_ELEMENT);
|
||||||
|
jscript.append(L"var result = findElement(arguments[0], arguments[1]);")
|
||||||
|
.append(L"if (!result) {")
|
||||||
|
.append(L"var e = Error('Unable to locate element');")
|
||||||
|
.append(L"e.code = ")
|
||||||
|
.append(UTF8ToWide(base::IntToString(kNoSuchElement)))
|
||||||
|
.append(L";throw e;")
|
||||||
|
.append(L"} else { return result; }");
|
||||||
|
} else {
|
||||||
|
jscript = build_atom(FIND_ELEMENTS, sizeof FIND_ELEMENT);
|
||||||
|
jscript.append(L"return findElements(arguments[0], arguments[1]);");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The element search needs to loop until at least one element is found or the
|
||||||
|
// session's implicit wait timeout expires, whichever occurs first.
|
||||||
|
base::Time start_time = base::Time::Now();
|
||||||
|
|
||||||
|
while (!done) {
|
||||||
|
if (result) {
|
||||||
|
delete result;
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = session_->ExecuteScript(jscript, args.get(), &result);
|
||||||
|
if (error == kSuccess) {
|
||||||
|
// If searching for many elements, make sure we found at least one before
|
||||||
|
// stopping.
|
||||||
|
done = find_one_element_ ||
|
||||||
|
(result->GetType() == Value::TYPE_LIST &&
|
||||||
|
static_cast<ListValue*>(result)->GetSize() > 0);
|
||||||
|
} else if (error != kNoSuchElement) {
|
||||||
|
SET_WEBDRIVER_ERROR(response, "Internal error in find_element atom",
|
||||||
|
kInternalServerError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 elapsed_time = (base::Time::Now() - start_time).InMilliseconds();
|
||||||
|
done = done || elapsed_time > session_->implicit_wait();
|
||||||
|
PlatformThread::Sleep(50); // Prevent a busy loop that eats the cpu.
|
||||||
|
}
|
||||||
|
|
||||||
|
response->set_value(result);
|
||||||
|
response->set_status(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webdriver
|
||||||
|
|
74
chrome/test/webdriver/commands/find_element_commands.h
Normal file
74
chrome/test/webdriver/commands/find_element_commands.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef CHROME_TEST_WEBDRIVER_COMMANDS_FIND_ELEMENT_COMMANDS_H_
|
||||||
|
#define CHROME_TEST_WEBDRIVER_COMMANDS_FIND_ELEMENT_COMMANDS_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "chrome/test/webdriver/commands/command.h"
|
||||||
|
#include "chrome/test/webdriver/commands/webdriver_command.h"
|
||||||
|
|
||||||
|
namespace webdriver {
|
||||||
|
|
||||||
|
// Base class for searching a page, this class can find either a single
|
||||||
|
// webelement or return multiple matches.
|
||||||
|
class FindElementCommand : public WebDriverCommand {
|
||||||
|
public:
|
||||||
|
FindElementCommand(const std::vector<std::string>& path_segments,
|
||||||
|
const DictionaryValue* const parameters,
|
||||||
|
const bool find_one_element)
|
||||||
|
: WebDriverCommand(path_segments, parameters),
|
||||||
|
find_one_element_(find_one_element) {}
|
||||||
|
virtual ~FindElementCommand() {}
|
||||||
|
|
||||||
|
virtual bool Init(Response* const response);
|
||||||
|
|
||||||
|
virtual bool DoesPost() { return true; }
|
||||||
|
virtual void ExecutePost(Response* const response);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual bool RequiresValidTab() { return false; }
|
||||||
|
const bool find_one_element_;
|
||||||
|
std::string root_element_id_;
|
||||||
|
std::string use_;
|
||||||
|
std::string value_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(FindElementCommand);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Search for an element on the page, starting from the document root.
|
||||||
|
// The located element will be returned as a WebElement JSON object. See:
|
||||||
|
// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/element
|
||||||
|
class FindOneElementCommand : public FindElementCommand {
|
||||||
|
public:
|
||||||
|
FindOneElementCommand(const std::vector<std::string>& path_segments,
|
||||||
|
const DictionaryValue* const parameters)
|
||||||
|
: FindElementCommand(path_segments, parameters, true) {}
|
||||||
|
virtual ~FindOneElementCommand() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(FindOneElementCommand);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Search for multiple elements on the page, starting from the identified
|
||||||
|
// element. The located elements will be returned as a WebElement JSON
|
||||||
|
// objects. See:
|
||||||
|
// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/element/:id/elements
|
||||||
|
class FindManyElementsCommand : public FindElementCommand {
|
||||||
|
public:
|
||||||
|
FindManyElementsCommand(const std::vector<std::string>& path_segments,
|
||||||
|
const DictionaryValue* const parameters)
|
||||||
|
: FindElementCommand(path_segments, parameters, false) {}
|
||||||
|
virtual ~FindManyElementsCommand() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(FindManyElementsCommand);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webdriver
|
||||||
|
|
||||||
|
#endif // CHROME_TEST_WEBDRIVER_COMMANDS_FIND_ELEMENT_COMMANDS_H_
|
||||||
|
|
45
chrome/test/webdriver/commands/implicit_wait_command.cc
Normal file
45
chrome/test/webdriver/commands/implicit_wait_command.cc
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "base/utf_string_conversions.h"
|
||||||
|
#include "chrome/test/webdriver/commands/implicit_wait_command.h"
|
||||||
|
|
||||||
|
namespace webdriver {
|
||||||
|
|
||||||
|
bool ImplicitWaitCommand::Init(Response* const response) {
|
||||||
|
if (!(WebDriverCommand::Init(response))) {
|
||||||
|
SET_WEBDRIVER_ERROR(response, "Failure on Init for find element",
|
||||||
|
kInternalServerError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record the requested wait time.
|
||||||
|
if (!GetIntegerParameter("ms", &ms_to_wait_)) {
|
||||||
|
SET_WEBDRIVER_ERROR(response, "Request missing ms parameter",
|
||||||
|
kBadRequest);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImplicitWaitCommand::ExecutePost(Response* const response) {
|
||||||
|
// Validate the wait time before setting it to the session.
|
||||||
|
if (ms_to_wait_ < 0) {
|
||||||
|
SET_WEBDRIVER_ERROR(response, "Wait must be non-negative",
|
||||||
|
kBadRequest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
session_->set_implicit_wait(ms_to_wait_);
|
||||||
|
LOG(INFO) << "Implicit wait set to: " << ms_to_wait_ << " ms";
|
||||||
|
|
||||||
|
response->set_value(new StringValue("success"));
|
||||||
|
response->set_status(kSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webdriver
|
||||||
|
|
42
chrome/test/webdriver/commands/implicit_wait_command.h
Normal file
42
chrome/test/webdriver/commands/implicit_wait_command.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef CHROME_TEST_WEBDRIVER_COMMANDS_IMPLICIT_WAIT_COMMAND_H_
|
||||||
|
#define CHROME_TEST_WEBDRIVER_COMMANDS_IMPLICIT_WAIT_COMMAND_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "chrome/test/webdriver/commands/webdriver_command.h"
|
||||||
|
|
||||||
|
namespace webdriver {
|
||||||
|
|
||||||
|
// Set the amount of time the driver should wait when searching for elements.
|
||||||
|
// If this command is never sent, the driver will default to an implicit wait
|
||||||
|
// of 0 ms. Until the webelement commands are checked in we do no use this
|
||||||
|
// variable. For more information see:
|
||||||
|
// http://code.google.com/p/selenium/wiki/JsonWireProtocol#/session/:sessionId/timeouts/implicit_wait
|
||||||
|
class ImplicitWaitCommand : public WebDriverCommand {
|
||||||
|
public:
|
||||||
|
inline ImplicitWaitCommand(const std::vector<std::string>& path_segments,
|
||||||
|
const DictionaryValue* const parameters)
|
||||||
|
: WebDriverCommand(path_segments, parameters), ms_to_wait_(0) {}
|
||||||
|
virtual ~ImplicitWaitCommand() {}
|
||||||
|
|
||||||
|
virtual bool Init(Response* const response);
|
||||||
|
|
||||||
|
virtual bool DoesPost() { return true; }
|
||||||
|
virtual void ExecutePost(Response* const response);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int ms_to_wait_;
|
||||||
|
virtual bool RequiresValidTab() { return true; }
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(ImplicitWaitCommand);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webdriver
|
||||||
|
|
||||||
|
#endif // CHROME_TEST_WEBDRIVER_COMMANDS_IMPLICIT_WAIT_COMMAND_H_
|
||||||
|
|
@@ -26,6 +26,8 @@
|
|||||||
#include "chrome/test/webdriver/utility_functions.h"
|
#include "chrome/test/webdriver/utility_functions.h"
|
||||||
#include "chrome/test/webdriver/commands/create_session.h"
|
#include "chrome/test/webdriver/commands/create_session.h"
|
||||||
#include "chrome/test/webdriver/commands/execute_command.h"
|
#include "chrome/test/webdriver/commands/execute_command.h"
|
||||||
|
#include "chrome/test/webdriver/commands/find_element_commands.h"
|
||||||
|
#include "chrome/test/webdriver/commands/implicit_wait_command.h"
|
||||||
#include "chrome/test/webdriver/commands/navigate_commands.h"
|
#include "chrome/test/webdriver/commands/navigate_commands.h"
|
||||||
#include "chrome/test/webdriver/commands/session_with_id.h"
|
#include "chrome/test/webdriver/commands/session_with_id.h"
|
||||||
#include "chrome/test/webdriver/commands/source_command.h"
|
#include "chrome/test/webdriver/commands/source_command.h"
|
||||||
@@ -68,6 +70,13 @@ void InitCallbacks(struct mg_context* ctx) {
|
|||||||
SetCallback<URLCommand>(ctx, "/session/*/url");
|
SetCallback<URLCommand>(ctx, "/session/*/url");
|
||||||
SetCallback<SpeedCommand>(ctx, "/session/*/speed");
|
SetCallback<SpeedCommand>(ctx, "/session/*/speed");
|
||||||
|
|
||||||
|
// WebElement commands
|
||||||
|
SetCallback<ImplicitWaitCommand>(ctx, "/session/*/timeouts/implicit_wait");
|
||||||
|
SetCallback<FindOneElementCommand>(ctx, "/session/*/element");
|
||||||
|
SetCallback<FindManyElementsCommand>(ctx, "/session/*/elements");
|
||||||
|
SetCallback<FindOneElementCommand>(ctx, "/session/*/element/*/element");
|
||||||
|
SetCallback<FindManyElementsCommand>(ctx, "/session/*/elements/*/elements");
|
||||||
|
|
||||||
// Since the /session/* is a wild card that would match the above URIs, this
|
// Since the /session/* is a wild card that would match the above URIs, this
|
||||||
// line MUST be the last registered URI with the server.
|
// line MUST be the last registered URI with the server.
|
||||||
SetCallback<SessionWithID>(ctx, "/session/*");
|
SetCallback<SessionWithID>(ctx, "/session/*");
|
||||||
@@ -80,7 +89,7 @@ void InitCallbacks(struct mg_context* ctx) {
|
|||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
struct mg_context *ctx;
|
struct mg_context *ctx;
|
||||||
base::AtExitManager exit;
|
base::AtExitManager exit;
|
||||||
std::string port = "8080";
|
std::string port = "9515";
|
||||||
#ifdef OS_POSIX
|
#ifdef OS_POSIX
|
||||||
CommandLine cmd_line = CommandLine(argc, argv);
|
CommandLine cmd_line = CommandLine(argc, argv);
|
||||||
#elif OS_WIN
|
#elif OS_WIN
|
||||||
@@ -110,14 +119,14 @@ int main(int argc, char *argv[]) {
|
|||||||
session->SetIPAddress(port);
|
session->SetIPAddress(port);
|
||||||
|
|
||||||
// Initialize SHTTPD context.
|
// Initialize SHTTPD context.
|
||||||
// Listen on port 8080 or port specified on command line.
|
// Listen on port 9515 or port specified on command line.
|
||||||
// TODO(jmikhail) Maybe add port 8081 as a secure connection.
|
// TODO(jmikhail) Maybe add port 9516 as a secure connection.
|
||||||
ctx = mg_start();
|
ctx = mg_start();
|
||||||
mg_set_option(ctx, "ports", port.c_str());
|
mg_set_option(ctx, "ports", port.c_str());
|
||||||
|
|
||||||
webdriver::InitCallbacks(ctx);
|
webdriver::InitCallbacks(ctx);
|
||||||
|
|
||||||
std::cout << "Starting server" << std::endl;
|
std::cout << "Starting server on port: " << port << std::endl;
|
||||||
// The default behavior is to run this service forever.
|
// The default behavior is to run this service forever.
|
||||||
while (true)
|
while (true)
|
||||||
PlatformThread::Sleep(3600);
|
PlatformThread::Sleep(3600);
|
||||||
|
@@ -18,8 +18,10 @@ import time
|
|||||||
import types
|
import types
|
||||||
import unittest
|
import unittest
|
||||||
import urllib2
|
import urllib2
|
||||||
from selenium.remote.webdriver import WebDriver
|
|
||||||
from selenium.common.exceptions import ErrorInResponseException
|
from selenium.common.exceptions import ErrorInResponseException
|
||||||
|
from selenium.common.exceptions import NoSuchElementException
|
||||||
|
from selenium.remote.webdriver import WebDriver
|
||||||
|
from selenium.remote.webdriver.webelement import WebElement
|
||||||
from urlparse import urlparse
|
from urlparse import urlparse
|
||||||
|
|
||||||
|
|
||||||
@@ -42,6 +44,19 @@ if not WEBDRIVER_SERVER_URL:
|
|||||||
WEBDRIVER_SERVER_URL = 'http://localhost:%d' % WEBDRIVER_PORT
|
WEBDRIVER_SERVER_URL = 'http://localhost:%d' % WEBDRIVER_PORT
|
||||||
|
|
||||||
class RemoteWebDriverTest(unittest.TestCase):
|
class RemoteWebDriverTest(unittest.TestCase):
|
||||||
|
SEARCH = "http://www.google.com/webhp?hl=en"
|
||||||
|
NEWS = "http://www.google.com/news?hl=en"
|
||||||
|
|
||||||
|
"""Verifies that navigation to a specific page is correct by asserting on the
|
||||||
|
the reported URL. The function will not work with pages that redirect."""
|
||||||
|
def navigate(self, url):
|
||||||
|
self.driver.get(url)
|
||||||
|
self.assertURL(url)
|
||||||
|
|
||||||
|
def assertURL(self, url):
|
||||||
|
u = self.driver.get_current_url()
|
||||||
|
self.assertEqual(u, url)
|
||||||
|
|
||||||
"""A new instance of chrome driver is started for every test case"""
|
"""A new instance of chrome driver is started for every test case"""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
global WEBDRIVER_SERVER_URL
|
global WEBDRIVER_SERVER_URL
|
||||||
@@ -81,6 +96,50 @@ class RemoteWebDriverTest(unittest.TestCase):
|
|||||||
search = string.lower(search)
|
search = string.lower(search)
|
||||||
self.assertNotEqual(-1, string.find(text, search))
|
self.assertNotEqual(-1, string.find(text, search))
|
||||||
|
|
||||||
|
class TestFindElement(RemoteWebDriverTest):
|
||||||
|
def testFindByName(self):
|
||||||
|
navigate(SEARCH)
|
||||||
|
# Find the Google search button.
|
||||||
|
q = self.driver.find_element_by_name("q")
|
||||||
|
self.assertTrue(isinstance(q, WebElement))
|
||||||
|
# Trying looking for an element not on the page.
|
||||||
|
self.assertRaises(NoSuchElementException,
|
||||||
|
self.driver.find_elment_by_name, "q2")
|
||||||
|
# Try to find the Google search button using the multiple find method.
|
||||||
|
q = self.driver.find_elements_by_name("q")
|
||||||
|
self.assertTrue(isinstance(q, list))
|
||||||
|
self.assertTrue(len(q), 1)
|
||||||
|
self.assertTrue(isinstance(q[0], WebElement))
|
||||||
|
# Try finding something not on page, with multiple find an empty array
|
||||||
|
# should return and no exception thrown.
|
||||||
|
q = self.driver.find_elements_by_name("q2")
|
||||||
|
assertTrue(q == [])
|
||||||
|
# Find a hidden element on the page
|
||||||
|
q = self.driver.find_element_by_name("oq")
|
||||||
|
self.assertTrue(isinstance(q, WebElement))
|
||||||
|
|
||||||
|
def testFindElementById(self):
|
||||||
|
navigate(SEARCH)
|
||||||
|
# Find the padding for the logo near the search bar.
|
||||||
|
elem = self.driver.find_element_by_id("logocont")
|
||||||
|
self.assertTrue(isinstance(elem, WebElement))
|
||||||
|
# Look for an ID not there.
|
||||||
|
self.assertRaises(NoSuchElementException,
|
||||||
|
self.driver.find_element_by_id, "logocont")
|
||||||
|
|
||||||
|
def testFindElementById0WithTimeout(self):
|
||||||
|
self.set_implicit_wait(0)
|
||||||
|
navigate(SEARCH)
|
||||||
|
# Find the padding for the logo near the search bar.
|
||||||
|
elem = self.driver.find_element_by_id("logocont")
|
||||||
|
self.assertTrue(isinstance(elem, WebElement))
|
||||||
|
self.set_implicit_wait(5000)
|
||||||
|
navigate(SEARCH)
|
||||||
|
# Look for an ID not there.
|
||||||
|
self.assertRaises(NoSuchElementException,
|
||||||
|
self.driver.find_element_by_id, "logocont")
|
||||||
|
|
||||||
|
|
||||||
class TestJavaScriptExecution(RemoteWebDriverTest):
|
class TestJavaScriptExecution(RemoteWebDriverTest):
|
||||||
""" Test the execute javascript ability of the remote driver"""
|
""" Test the execute javascript ability of the remote driver"""
|
||||||
def testNoModification(self):
|
def testNoModification(self):
|
||||||
@@ -120,19 +179,6 @@ class TestJavaScriptExecution(RemoteWebDriverTest):
|
|||||||
|
|
||||||
|
|
||||||
class TestNavigation(RemoteWebDriverTest):
|
class TestNavigation(RemoteWebDriverTest):
|
||||||
SEARCH = "http://www.google.com/webhp?hl=en"
|
|
||||||
NEWS = "http://www.google.com/news?hl=en"
|
|
||||||
|
|
||||||
"""Verifies that navigation to a specific page is correct by asserting on the
|
|
||||||
the reported URL. The function will not work with pages that redirect."""
|
|
||||||
def navigate(self, url):
|
|
||||||
self.driver.get(url)
|
|
||||||
self.assertURL(url)
|
|
||||||
|
|
||||||
def assertURL(self, url):
|
|
||||||
u = self.driver.get_current_url()
|
|
||||||
self.assertEqual(u, url)
|
|
||||||
|
|
||||||
def testNavigateToURL(self):
|
def testNavigateToURL(self):
|
||||||
# No redirects are allowed on the google home page.
|
# No redirects are allowed on the google home page.
|
||||||
self.navigate(self.SEARCH)
|
self.navigate(self.SEARCH)
|
||||||
|
@@ -173,6 +173,17 @@ class WebDriver(object):
|
|||||||
resp = self._execute(Command.GET_TITLE)
|
resp = self._execute(Command.GET_TITLE)
|
||||||
return resp['value']
|
return resp['value']
|
||||||
|
|
||||||
|
def set_implicit_wait(self, wait):
|
||||||
|
"""Set the amount of time the driver should wait when searching for
|
||||||
|
elements. When searching for a single element, the driver should poll
|
||||||
|
the page until an element is found or the timeout expires, whichever
|
||||||
|
occurs first. When searching for multiple elements, the driver should
|
||||||
|
poll the page until at least one element is found or the timeout
|
||||||
|
expires, at which point it should return an empty list. If this
|
||||||
|
command is never sent, the driver should default to an implicit wait
|
||||||
|
of 0ms."""
|
||||||
|
self._execute(Command.IMPLICIT_WAIT, {'ms': wait})
|
||||||
|
|
||||||
def find_element_by_id(self, id_):
|
def find_element_by_id(self, id_):
|
||||||
"""Finds element by id."""
|
"""Finds element by id."""
|
||||||
return self._find_element_by("id", id_)
|
return self._find_element_by("id", id_)
|
||||||
|
@@ -76,4 +76,5 @@ class Command(object):
|
|||||||
GET_ELEMENT_ATTRIBUTE = "getElementAttribute"
|
GET_ELEMENT_ATTRIBUTE = "getElementAttribute"
|
||||||
GET_ELEMENT_VALUE_OF_CSS_PROPERTY = "getElementValueOfCssProperty"
|
GET_ELEMENT_VALUE_OF_CSS_PROPERTY = "getElementValueOfCssProperty"
|
||||||
ELEMENT_EQUALS = "elementEquals"
|
ELEMENT_EQUALS = "elementEquals"
|
||||||
|
IMPLICIT_WAIT = "setImplicitWait"
|
||||||
SCREENSHOT = "screenshot"
|
SCREENSHOT = "screenshot"
|
||||||
|
@@ -128,6 +128,7 @@ class RemoteConnection(object):
|
|||||||
Command.GET_CURRENT_URL: ('GET', '/session/$sessionId/url'),
|
Command.GET_CURRENT_URL: ('GET', '/session/$sessionId/url'),
|
||||||
Command.GET_TITLE: ('GET', '/session/$sessionId/title'),
|
Command.GET_TITLE: ('GET', '/session/$sessionId/title'),
|
||||||
Command.GET_PAGE_SOURCE: ('GET', '/session/$sessionId/source'),
|
Command.GET_PAGE_SOURCE: ('GET', '/session/$sessionId/source'),
|
||||||
|
Command.IMPLICIT_WAIT: ('POST', '/session/$sessionId/timeouts/implicit_wait'),
|
||||||
Command.SCREENSHOT: ('GET', '/session/$sessionId/screenshot'),
|
Command.SCREENSHOT: ('GET', '/session/$sessionId/screenshot'),
|
||||||
Command.SET_BROWSER_VISIBLE:
|
Command.SET_BROWSER_VISIBLE:
|
||||||
('POST', '/session/$sessionId/visible'),
|
('POST', '/session/$sessionId/visible'),
|
||||||
|
Reference in New Issue
Block a user