Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
CIRCLE
/
cloud
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
94
Merge Requests
10
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
A prog2-höz tartozó friss repo anyagok itt elérhetőek:
https://git.iit.bme.hu/
Commit
abcfee03
authored
Apr 02, 2015
by
Csók Tamás
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
selenium: stability upgrades, fallback action chains
parent
dc0834bd
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
198 additions
and
122 deletions
+198
-122
circle/dashboard/tests/selenium/util.py
+198
-122
No files found.
circle/dashboard/tests/selenium/util.py
View file @
abcfee03
...
...
@@ -24,7 +24,8 @@ import time
import
urlparse
from
selenium.common.exceptions
import
(
NoSuchElementException
,
StaleElementReferenceException
)
NoSuchElementException
,
StaleElementReferenceException
,
TimeoutException
)
from
selenium.webdriver.common.by
import
By
from
selenium.webdriver.support
import
expected_conditions
as
ec
from
selenium.webdriver.support.select
import
Select
...
...
@@ -35,7 +36,131 @@ from .config import SeleniumConfig
logger
=
logging
.
getLogger
(
SeleniumConfig
.
logger_name
)
class
CircleSeleniumMixin
(
object
):
class
SeleniumMixin
(
object
):
def
list_options
(
self
,
select
):
try
:
option_dic
=
{}
select
=
Select
(
select
)
for
option
in
select
.
options
:
key
=
option
.
get_attribute
(
'value'
)
if
key
is
not
None
and
key
:
option_dic
[
key
]
=
[
option
.
text
]
return
option_dic
except
:
logger
.
exception
(
"Selenium cannot list the"
" select possibilities"
)
raise
Exception
(
'Cannot list the select possibilities'
)
def
select_option
(
self
,
select
,
what
=
None
):
"""
From an HTML select imput type try to choose the specified one.
Select is a selenium web element type. What represent both the
text of the option and it's ID.
"""
try
:
my_choice
=
None
options
=
self
.
list_options
(
select
)
select
=
Select
(
select
)
if
what
is
not
None
:
for
key
,
value
in
options
.
iteritems
():
if
what
in
key
:
my_choice
=
key
else
:
if
isinstance
(
value
,
list
):
for
single_value
in
value
:
if
what
in
single_value
:
my_choice
=
key
else
:
if
what
in
value
:
my_choice
=
key
if
my_choice
is
None
:
my_choose_list
=
options
.
keys
()
my_choice
=
my_choose_list
[
random
.
randint
(
0
,
len
(
my_choose_list
)
-
1
)]
select
.
select_by_value
(
my_choice
)
except
:
logger
.
exception
(
"Selenium cannot select the chosen one"
)
raise
Exception
(
'Cannot select the chosen one'
)
def
get_link_by_href
(
self
,
target_href
,
attributes
=
None
):
try
:
links
=
self
.
driver
.
find_elements_by_tag_name
(
'a'
)
for
link
in
links
:
href
=
link
.
get_attribute
(
'href'
)
if
href
is
not
None
and
href
:
if
target_href
in
href
:
perfect_fit
=
True
if
isinstance
(
attributes
,
dict
):
for
key
,
target_value
in
attributes
.
iteritems
():
attr_check
=
link
.
get_attribute
(
key
)
if
attr_check
is
not
None
and
attr_check
:
if
target_value
not
in
attr_check
:
perfect_fit
=
False
if
perfect_fit
:
return
link
except
:
logger
.
exception
(
"Selenium cannot find the href=
%
s link"
%
target_href
)
raise
Exception
(
'Cannot find the requested href'
)
def
click_on_link
(
self
,
link
):
"""
There are situations when selenium built in click() function
doesn't work as intended, that's when this function is used.
Fires a click event via javascript injection.
"""
try
:
# Javascript function to simulate a click on a link
javascript
=
"""
var link = arguments[0];
var cancelled = false;
if(document.createEvent) {
var event = document.createEvent("MouseEvents");
event.initMouseEvent(
"click", true, true, window, 0, 0, 0, 0, 0,
false,false,false,false,0,null);
cancelled = !link.dispatchEvent(event);
} else if(link.fireEvent) {
cancelled = !link.fireEvent("onclick");
} if (!cancelled) {
window.location = link.href;
}"""
self
.
driver
.
execute_script
(
javascript
,
link
)
except
:
logger
.
exception
(
"Selenium cannot inject javascript to the page"
)
raise
Exception
(
'Cannot inject javascript to the page'
)
def
get_text
(
self
,
node
,
tag
):
"""
There are some cases where selenium default WebElement text()
method returns less then it actually could contain. Solving that
here is a simple regular expression. Give the closest html element
then specify the html tag of the enclosed text.
"""
text
=
""
try
:
text_whole
=
re
.
search
(
r'<
%(tag)
s[^>]*>([^<]+)</
%(tag)
s>'
%
{
'tag'
:
tag
},
node
.
get_attribute
(
"outerHTML"
))
.
group
()
text_parts
=
text_whole
.
splitlines
()
for
part
in
text_parts
:
if
'<'
not
in
part
and
'>'
not
in
part
:
text
+=
part
text
=
text
.
replace
(
" "
,
""
)
except
:
return
node
.
text
if
len
(
node
.
text
)
>=
len
(
text
):
text
=
node
.
text
else
:
logger
.
warning
(
"Better text found which is '
%
s'"
%
text
)
return
text
.
strip
()
class
CircleSeleniumMixin
(
SeleniumMixin
):
def
login
(
self
,
location
=
None
):
driver
=
self
.
driver
if
location
is
None
:
...
...
@@ -76,7 +201,8 @@ class CircleSeleniumMixin(object):
logger
.
exception
(
"Selenium cannot find the form controls"
)
raise
Exception
(
'Cannot find the form controls'
)
def
wait_and_accept_operation
(
self
,
argument
=
None
):
def
wait_and_accept_operation
(
self
,
argument
=
None
,
try_wait
=
None
,
fallback_url
=
None
):
"""
Accepts the operation confirmation pop up window.
Fills out the text inputs before accepting if argument is given.
...
...
@@ -97,20 +223,56 @@ class CircleSeleniumMixin(object):
form
.
clear
()
form
.
send_keys
(
argument
)
accept
.
click
()
if
try_wait
is
not
None
:
try
:
WebDriverWait
(
self
.
driver
,
self
.
conf
.
wait_max_sec
)
.
until
(
ec
.
visibility_of_element_located
((
By
.
CSS_SELECTOR
,
try_wait
)))
except
TimeoutException
:
# Try to submit to form using other method
try
:
accept
=
WebDriverWait
(
self
.
driver
,
self
.
conf
.
wait_max_sec
)
.
until
(
ec
.
element_to_be_clickable
((
By
.
CLASS_NAME
,
"modal-accept"
)))
accept
.
find_element_by_css_selector
(
"form[method*='POST']"
)
.
submit
()
except
:
logger
.
exception
(
"Selenium couldn't find the modal at retry"
)
raise
Exception
(
"Cannot find the modal"
)
except
:
logger
.
exception
(
"Selenium couldn't find the specified css element"
)
raise
Exception
(
"Cannot find the css element"
)
except
:
logger
.
exception
(
"Selenium cannot accept the"
" operation confirmation"
)
if
fallback_url
is
not
None
:
logger
.
warning
(
"However error was anticipated falling back to
%(url)
s"
%
{
'url'
:
fallback_url
})
self
.
driver
.
get
(
fallback_url
)
self
.
wait_and_accept_operation
(
argument
,
try_wait
)
else
:
self
.
driver
.
save_screenshot
(
'error_at_try_wait.png'
)
raise
Exception
(
'Cannot accept the operation confirmation'
)
def
save_template_from_vm
(
self
,
name
):
try
:
url_base
=
urlparse
.
urlparse
(
self
.
driver
.
current_url
)
url_save
=
(
"
%(host)
s
%(url)
s"
%
{
'host'
:
self
.
conf
.
host
,
'url'
:
urlparse
.
urljoin
(
url_base
.
path
,
url_base
.
query
)})
WebDriverWait
(
self
.
driver
,
self
.
conf
.
wait_max_sec
)
.
until
(
ec
.
element_to_be_clickable
((
By
.
CSS_SELECTOR
,
"a[href$='/op/deploy/']"
)))
self
.
click_on_link
(
self
.
get_link_by_href
(
"/op/deploy/"
))
self
.
wait_and_accept_operation
()
fallback_url
=
"
%
sop/deploy/"
%
url_save
self
.
wait_and_accept_operation
(
try_wait
=
"a[href$='/op/shut_off/']"
,
fallback_url
=
fallback_url
)
recent_deploy
=
self
.
recently
(
self
.
get_timeline_elements
(
"vm.Instance.deploy"
))
if
not
self
.
check_operation_result
(
...
...
@@ -123,10 +285,9 @@ class CircleSeleniumMixin(object):
ec
.
element_to_be_clickable
((
By
.
CSS_SELECTOR
,
"a[href$='/op/shut_off/']"
))))
self
.
wait_and_accept_operation
()
WebDriverWait
(
self
.
driver
,
self
.
conf
.
wait_max_sec
)
.
until
(
ec
.
element_to_be_clickable
((
By
.
CSS_SELECTOR
,
"a[href$='/op/deploy/']"
)))
fallback_url
=
"
%
sop/shut_off/"
%
url_save
self
.
wait_and_accept_operation
(
try_wait
=
"a[href$='/op/deploy/']"
,
fallback_url
=
fallback_url
)
recent_shut_off
=
self
.
recently
(
self
.
get_timeline_elements
(
"vm.Instance.shut_off"
))
if
not
self
.
check_operation_result
(
...
...
@@ -140,6 +301,8 @@ class CircleSeleniumMixin(object):
By
.
CSS_SELECTOR
,
"a[href$='/op/save_as_template/']"
))))
self
.
wait_and_accept_operation
(
name
)
logger
.
warning
(
"Selenium created
%(name)
s template"
%
{
'name'
:
name
})
return
name
except
:
logger
.
exception
(
"Selenium cannot save a vm as a template"
)
...
...
@@ -150,7 +313,7 @@ class CircleSeleniumMixin(object):
method
=
None
,
op_system
=
None
,
lease
=
None
,
network
=
"vm"
):
if
name
is
None
:
name
=
"
template_
new_
%
s"
%
self
.
conf
.
client_name
name
=
"new_
%
s"
%
self
.
conf
.
client_name
if
op_system
is
None
:
op_system
=
"!os
%
s"
%
self
.
conf
.
client_name
try
:
...
...
@@ -213,7 +376,9 @@ class CircleSeleniumMixin(object):
templates
=
template_table
.
find_elements_by_css_selector
(
"td.name"
)
found_template_ids
=
[]
for
template
in
templates
:
if
name
is
None
or
name
in
template
.
text
:
# Little magic to outsmart accented naming errors
template_name
=
self
.
get_text
(
template
,
"a"
)
if
name
is
None
or
name
in
template_name
:
try
:
template_link
=
template
.
find_element_by_css_selector
(
css_selector_of_a_template
)
...
...
@@ -223,12 +388,21 @@ class CircleSeleniumMixin(object):
found_template_ids
.
append
(
template_id
)
logger
.
warning
(
"Found '
%(name)
s' "
"template's ID as
%(id)
s"
%
{
'name'
:
template
.
text
,
'name'
:
template
_name
,
'id'
:
template_id
})
except
NoSuchElementException
:
pass
except
:
raise
else
:
logger
.
warning
(
"Searching for
%(searched)
s so"
"
%(name)
s is dismissed"
%
{
'searched'
:
name
,
'name'
:
template_name
})
logger
.
warning
(
"Dismissed template html code:
%(code)
s"
%
{
'code'
:
template
.
get_attribute
(
"outerHTML"
)})
if
not
found_template_ids
and
name
is
not
None
:
logger
.
warning
(
"Selenium could not find the specified "
"
%(name)
s template in the list"
%
{
...
...
@@ -339,7 +513,7 @@ class CircleSeleniumMixin(object):
code_text
=
code
css_activity_selector
=
(
"div[data-activity-code="
"'
%(code)
s']"
%
{
'code'
:
code
_text
})
'code'
:
code
})
self
.
click_on_link
(
WebDriverWait
(
self
.
driver
,
self
.
conf
.
wait_max_sec
)
.
until
(
ec
.
element_to_be_clickable
((
...
...
@@ -378,7 +552,7 @@ class CircleSeleniumMixin(object):
def
create_template_from_base
(
self
,
delete_disk
=
True
,
name
=
None
):
try
:
if
name
is
None
:
name
=
"
template_from_base
_
%
s"
%
self
.
conf
.
client_name
name
=
"
from
_
%
s"
%
self
.
conf
.
client_name
self
.
driver
.
get
(
'
%
s/dashboard/template/choose/'
%
self
.
conf
.
host
)
choice_list
=
[]
choices
=
self
.
driver
.
find_elements_by_css_selector
(
...
...
@@ -402,14 +576,8 @@ class CircleSeleniumMixin(object):
if
len
(
disk_list
)
>
0
:
self
.
click_on_link
(
self
.
get_link_by_href
(
"/op/remove_disk/"
))
self
.
wait_and_accept_operation
()
WebDriverWait
(
self
.
driver
,
self
.
conf
.
wait_max_sec
)
.
until
(
ec
.
visibility_of_element_located
((
By
.
ID
,
"_activity"
)))
self
.
click_on_link
(
WebDriverWait
(
self
.
driver
,
self
.
conf
.
wait_max_sec
)
.
until
(
ec
.
element_to_be_clickable
((
By
.
CSS_SELECTOR
,
"a[href*='#activity']"
))))
self
.
wait_and_accept_operation
(
try_wait
=
"a[href*='#activity']"
)
recent_remove_disk
=
self
.
recently
(
self
.
get_timeline_elements
(
"vm.Instance.remove_disk"
))
...
...
@@ -454,10 +622,16 @@ class CircleSeleniumMixin(object):
'vm-create-template-summary'
)
choice
=
random
.
randint
(
0
,
len
(
vm_list
)
-
1
)
vm_list
[
choice
]
.
click
()
try
:
WebDriverWait
(
self
.
driver
,
self
.
conf
.
wait_max_sec
)
.
until
(
ec
.
element_to_be_clickable
((
By
.
CSS_SELECTOR
,
"button[class*='vm-create-start']"
)))
.
click
()
By
.
CLASS_NAME
,
"vm-create-start"
)))
.
click
()
except
TimeoutException
:
# Selenium can time out not findig it even though it is present
self
.
driver
.
find_element_by_tag_name
(
'form'
)
.
submit
()
except
:
logger
.
exception
(
"Selenium could not submit create vm form"
)
raise
Exception
(
'Could not submit a form'
)
WebDriverWait
(
self
.
driver
,
self
.
conf
.
wait_max_sec
)
.
until
(
ec
.
visibility_of_element_located
((
By
.
CLASS_NAME
,
'alert-success'
)))
...
...
@@ -498,7 +672,7 @@ class CircleSeleniumMixin(object):
self
.
driver
.
get
(
"
%(host)
s/dashboard/vm/
%(id)
s/op/destroy/"
%
{
'host'
:
self
.
conf
.
host
,
'id'
:
pk
})
self
.
wait_and_accept_operation
()
self
.
wait_and_accept_operation
(
try_wait
=
"a[href*='/op/recover/']"
)
try
:
status_span
=
WebDriverWait
(
self
.
driver
,
self
.
conf
.
wait_max_sec
)
.
until
(
...
...
@@ -528,101 +702,3 @@ class CircleSeleniumMixin(object):
except
:
logger
.
exception
(
"Selenium can not destroy a VM"
)
raise
Exception
(
"Can not destroy a VM"
)
class
SeleniumMixin
(
object
):
def
list_options
(
self
,
select
):
try
:
option_dic
=
{}
select
=
Select
(
select
)
for
option
in
select
.
options
:
key
=
option
.
get_attribute
(
'value'
)
if
key
is
not
None
and
key
:
option_dic
[
key
]
=
[
option
.
text
]
return
option_dic
except
:
logger
.
exception
(
"Selenium cannot list the"
" select possibilities"
)
raise
Exception
(
'Cannot list the select possibilities'
)
def
select_option
(
self
,
select
,
what
=
None
):
"""
From an HTML select imput type try to choose the specified one.
Select is a selenium web element type. What represent both the
text of the option and it's ID.
"""
try
:
my_choice
=
None
options
=
self
.
list_options
(
select
)
select
=
Select
(
select
)
if
what
is
not
None
:
for
key
,
value
in
options
.
iteritems
():
if
what
in
key
:
my_choice
=
key
else
:
if
isinstance
(
value
,
list
):
for
single_value
in
value
:
if
what
in
single_value
:
my_choice
=
key
else
:
if
what
in
value
:
my_choice
=
key
if
my_choice
is
None
:
my_choose_list
=
options
.
keys
()
my_choice
=
my_choose_list
[
random
.
randint
(
0
,
len
(
my_choose_list
)
-
1
)]
select
.
select_by_value
(
my_choice
)
except
:
logger
.
exception
(
"Selenium cannot select the chosen one"
)
raise
Exception
(
'Cannot select the chosen one'
)
def
get_link_by_href
(
self
,
target_href
,
attributes
=
None
):
try
:
links
=
self
.
driver
.
find_elements_by_tag_name
(
'a'
)
for
link
in
links
:
href
=
link
.
get_attribute
(
'href'
)
if
href
is
not
None
and
href
:
if
target_href
in
href
:
perfect_fit
=
True
if
isinstance
(
attributes
,
dict
):
for
key
,
target_value
in
attributes
.
iteritems
():
attr_check
=
link
.
get_attribute
(
key
)
if
attr_check
is
not
None
and
attr_check
:
if
target_value
not
in
attr_check
:
perfect_fit
=
False
if
perfect_fit
:
return
link
except
:
logger
.
exception
(
"Selenium cannot find the href=
%
s link"
%
target_href
)
raise
Exception
(
'Cannot find the requested href'
)
def
click_on_link
(
self
,
link
):
"""
There are situations when selenium built in click() function
doesn't work as intended, that's when this function is used.
Fires a click event via javascript injection.
"""
try
:
# Javascript function to simulate a click on a link
javascript
=
(
"var link = arguments[0];"
"var cancelled = false;"
"if(document.createEvent) {"
" var event = document.createEvent(
\"
MouseEvents
\"
);"
" event.initMouseEvent("
"
\"
click
\"
, true, true, window, 0, 0, 0, 0, 0,"
" false,false,false,false,0,null);"
" cancelled = !link.dispatchEvent(event);"
"} else if(link.fireEvent) {"
" cancelled = !link.fireEvent(
\"
onclick
\"
);"
"} if (!cancelled) {"
" window.location = link.href;"
"}"
)
self
.
driver
.
execute_script
(
javascript
,
link
)
except
:
logger
.
exception
(
"Selenium cannot inject javascript to the page"
)
raise
Exception
(
'Cannot inject javascript to the page'
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment