Reputation: 10961
I have the following page layout:
<div class="x1">
<button aria-expanded="false" class="button" data-toggle="dropdown" type="button">Actions<span class="caret"></span></button>
<ul class="dropdown-menu" role="menu">
<li>
<a href="<my_link>/start">Start</a>
</li>
<li>
<a data-target="delete" data-toggle="modal">Delete</a>
</li>
<li>
<a href="<my_link>/auth">Authenticate</a>
</li>
</ul>
</div>
Each one of these represent a button ("Action"), which when clicked will present a dropdown menu between Start
, Delete
, and Authenticate
.
I'm trying to automate my page test from the backend using Selenium
and Python
.
Here what I have so far:
def scan_page(action):
scan_url = urlparse.urljoin(self.base_url, "foo")
self.driver.get(scan_url)
elements = self.driver.find_elements_by_xpath("//div[@class='x1']")
# loop over all the elements found by xpath
for element in elements:
element.click()
ul = element.find_element_by_class_name("dropdown-menu")
if action == "scan":
if "Start" in ul.text:
# start the action
button = element.find_element_by_xpath("//button[@data-toggle='dropdown']")
button.click()
elif action == "delete":
if "Delete" in ul.text:
self.log.info("Deleting...")
elif action == "auth":
if "auth" in ul.text:
self.log.info("Authenticating...")
else:
continue
The function is given an action
, which define what is to be done. If "start"
then loops over all the elements
and click the Start
option. However, it doesn't look like it's going over all the buttons
defined in the page, and only the first button
is being started. So, for some reason, the Delete
option is somehow selected.
What am I doing wrong?
I've added a JS Fiddle so people can play with that: http://jsfiddle.net/58rs3kuk/1/
Upvotes: 1
Views: 154
Reputation: 25597
I found and fixed a few issues. I think this should work or at least get you on the right track.
1) You were clicking the container DIV
which isn't necessary. It probably doens't hurt, it just doesn't do anything productive.
2) You were clicking BUTTON
only if action = "scan"
. You want to click BUTTON
for all actions so those lines need to move up before the IF
starts. So... you will 1. click the BUTTON
, 2. determine what action was requested, and 3. perform that action.
3) You were grabbing the UL
to get the text but the text you want is in the LI
(but is not needed after the changes I made).
4) I changed the names of some of the variables to make them more identifiable, elements
is now buttonContainers
and element
is now buttonContainer
. I would suggest you follow this practice because it will help you (and others) debug your code more easily.
5) Since we know the order of the actions in each button and they are all the same, we don't have to look for the text in the link... we can just click them by index: 0 for Start, 1 for Delete, 2 for Authenticate.
6) Added a warning in the logs if an invalid action is passed. You should probably change that to an exception or whatever is appropriate in your scripts.
7) Fixed the indent of the code you posted
def scan_page(action):
scan_url = urlparse.urljoin(self.base_url, "foo")
self.driver.get(scan_url)
buttonContainers = self.driver.find_elements_by_xpath("//div[@class='x1']")
# loop over all the buttonContainers
for buttonContainer in buttonContainers:
buttonContainer.find_element_by_tag_name("button").click()
lis = buttonContainer.find_elements_by_tag_name("li")
if action == "start":
lis[0].click() # because we know the order of the actions and they are the same in each button, we can just click on them by index.
self.log.info("Starting...")
elif action == "delete":
lis[1].click()
self.log.info("Deleting...")
elif action == "auth":
lis[2].click()
self.log.info("Authenticating...")
else:
self.log.info("WARNING: " + action + " is not a valid action.")
continue
Upvotes: 1