Trying to apply a selenium test on bootstrap modal using python - python

Here is the HTML:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div class="modal-content">
<div class="modal-header">
<h5 id="add-title" class="modal-title">Add a text</h5>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<section id="add-popup-card-body">
<form id="add-form"><div class="sm-form modal-body">
<h6 id="add-popup-card-body-subtitle" class="card-subtitle mb-2 text-muted">Please enter text</h6>
<input type="text" id="add-input-form" class="sm-form modal-body form-control validate" pattern="\S+" style="text-transform:uppercase" maxlength="32" placeholder="tag" onkeyup="this.value = this.value.toUpperCase();" required="">
<div><small>*Spaces are not allowed</small></div>
</div>`enter code here`
<div class="modal-footer justify-content-center">
<input type="submit" class="btn btn-primary">
</div></form>
</section>
</div>
</body>
</html>
All that I need is to find a way to make Selenium test close the modal. I have tried these so far and none worked:
self.driver.findElement(By.className("close")).click()
self.driver.findElement(By.xpath("//button[#class = 'close']")).click()
self.driver.find_element(By.CSS_SELECTOR, 'button[class="close"]').click()

There are basically 4 ways to click in Selenium.
I will use this xpath
//button[#class='close' and #data-dismiss='modal' and text()='×']
Code trial 1:
time.sleep(5)
driver.find_element_by_xpath("//button[#class='close' and #data-dismiss='modal' and text()='×']").click()
Code trial 2:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#class='close' and #data-dismiss='modal' and text()='×']"))).click()
Code trial 3:
time.sleep(5)
button = driver.find_element_by_xpath("//button[#class='close' and #data-dismiss='modal' and text()='×']")
driver.execute_script("arguments[0].click();", button)
Code trial 4:
time.sleep(5)
button = driver.find_element_by_xpath("//button[#class='close' and #data-dismiss='modal' and text()='×']")
ActionChains(driver).move_to_element(button).click().perform()
Imports:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
PS : Please check in the dev tools (Google chrome) if we have unique entry in HTML DOM or not.
Steps to check:
Press F12 in Chrome -> go to element section -> do a CTRL + F -> then paste the xpath and see, if your desired element is getting highlighted with 1/1 matching node.

To click on the element you can use either of the following Locator Strategies:
Using css_selector:
driver.find_element(By.CSS_SELECTOR, "button.close[data-dismiss='modal']").click()
Using xpath:
driver.find_element(By.XPATH, "//button[#class='close' and #data-dismiss='modal'][text()='×']").click()
Ideally, as the desired element is a Modal Dialog Box to click on the clickable element you need to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.close[data-dismiss='modal']"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#class='close' and #data-dismiss='modal'][text()='×']"))).click()
Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

Thanks for the help. I have tried all the above solution but none worked. I was getting similar errors. After some reading I called an id that was above the "modal-content" and added 3 div . By using this code :
self.driver.find_element_by_xpath("//*[#id='add-tag popup']/div/div/div/button").click()

Related

Error in Clicking on SVG using Selenium Python

Following is HTML code. I want to click on Export to CSV.
<pre>
<div id="leo-title-bar" style="width: 100%">
<div class="container-fluid p-0"><div class="no-gutters" style="min-height: 100vh;">
<div class="col-12 d-flex flex-column">
<nav class="navbar navbar-dark bg-primary justify-content-start" style="height: 64px; flex-wrap: unset;">
<span class="navbar-brand" style="flex: 1 1 0%; font-size: 22px;">Agency Summary</span>
<svg aria-labelledby="svg-inline--fa-title-5AhAR2Z9sKF8" data-prefix="fas" data-icon="download" class="svg-inline--fa fa-download fa-w-16 svg-shadow svg-icon-basic svg-icon-basic-hover" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<title id="svg-inline--fa-title-5AhAR2Z9sKF8">Export to CSV</title>
<path fill="currentColor" d="M216 0h80c13....."></path></svg>
</div></main>
</div>
</div>
</div>
</div>
</pre>
I have tried following code:
from selenium import webdriver
driver = webdriver.Edge(PATH)
driver.find_element_by_xpath('//div[#class="col-12 d-flex flex-column"]/*[name()="svg"][#aria-labelledby="svg-inline--fa-title-5AhAR2Z9sKF8"]').click()
Getting an error:
selenium.common.exceptions.NoSuchElementException
Possibly you are missing a delay.
So adding some dummy sleep like
from selenium import webdriver
import time
driver = webdriver.Edge(PATH)
time.sleep(5)
driver.find_element_by_xpath('//div[#class="col-12 d-flex flex-column"]/*[name()="svg"][#aria-labelledby="svg-inline--fa-title-5AhAR2Z9sKF8"]').click()
Should resolve your problem.
Also your locator looks bad. You have to create more reliable locator.
Also you should use Expected Conditions explicit waits, as following:
from selenium import webdriver
import time
rom selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Edge(PATH)
wait = WebDriverWait(driver, 20)
wait.until(EC.visibility_of_element_located((By.XPATH, '//div[#class="col-12 d-flex flex-column"]/*[name()="svg"][#aria-labelledby="svg-inline--fa-title-5AhAR2Z9sKF8"]'))).click()
Change
.../*[name()="svg"]...
to
.../*[local-name()="svg"]...
in your XPath-expression, because your <svg...> element is in the namespace xmlns="http://www.w3.org/2000/svg". Thing is that name() matches namespace:name, but local-name() only matches the name without the namespace(-prefix).
The desired element is a svg element. To click() on the element you have to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div#leo-title-bar svg[data-icon='download']"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[#id='leo-title-bar']//*[name()='svg' and #data-icon='download']"))).click()
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
References
You can find a couple of relevant discussions on interacting with SVG element in:
How to access to 'rect' type element through Selenium-Python
Clicking on svg using selenium python

Upload file with Selenium when more than 1 Input with same class detected

So I have page structured like this :
<ul>
<li>
<div>
<div>
<span class="buttonUpload" custom="call.js">Button Upload</span>
<input class="fa-cloud-upload" name="file" type="file" accept="">
</div>
</div>
</li>
<li>
<div>
<div>
<span class="buttonUpload" custom="call.js">Button Upload</span>
<input class="fa-cloud-upload" name="file" type="file" accept="">
</div>
</div>
</li>
<li>
<div>
<div>
<span class="buttonUpload" custom="call.js">Button Upload</span>
<input class="fa-cloud-upload" name="file" type="file" accept="">
</div>
</div>
</li>
</ul>
I want to upload file only to the first input tag using send_keys() from selenium but for some reason it's not working, if there's only single li tags shown after refresh then the codes work, my code as bellow :
view_videos = WebDriverWait(driver, self.latency).until(EC.visibility_of_all_elements_located(
(By.CSS_SELECTOR, "a[i18n='i18n.openLink']")))
for i in range(len(view_videos)):
# some other script here
uploadme = "/home/user/myfile.png"
#script to upload
driver.find_element_by_css_selector("input[class='fa-cloud-upload']").send_keys(str(uploadme))
I even try with driver wait and select all element with selected array:
#script to upload
upload_first = WebDriverWait(driver, self.latency).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "input[class='fa-cloud-upload']")))
upload_first[0].send_keys(str(uploadme))
But nothing happened, I execute also javascript to erase 2 <li> tags after the first one before upload but still upload not working, nothing happens, I just want to upload to first input only using selenium, any clue?
Try using By.CLASS_NAME, 'fa-cloud-upload' or EC.presense_of_element_located((By.XPATH, 'its xpath'))
You can find Xpath of the element in F12 panel. Inspect the element, then right click on it in F12 panel and copy -> Xpath.
To send a character sequence to the first <input> tag instead of presence_of_all_elements_located() you have to induce WebDriverWait for the element_to_be_clickable() and you can use either of the following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "ul > li input.fa-cloud-upload"))).send_keys(str(uploadme))
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//ul/li//input[#class='fa-cloud-upload']"))).send_keys(str(uploadme))
Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

Can not find div by class name via Selenium(Python)

I am trying to access the "events" inside the div with class name "rps-wrapper" within the url http://gridworlds-multiplayer.org/ but when I use the function I get an error.
<div class="rps-wrapper">
<ul id="events"></ul>
<div class="controls">
<div class="chat-wrapper">
<form id="chat-form">
<input id="chat" autocomplete="off" title="chat"/>
<button id="say">Say</button>
</form>
</div>
</div>
</div>
<script src="/socket.io/socket.io.js"></script>
<script src="src/client.js"></script>
</body>
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('*the site is here*')
rps_wrapper = driver.find_element_by_class_name('rps-wrapper')
Should get the div with class name rps-wrapper, but outputs error elenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".rps-wrapper"}
(Session info: chrome=75.0.3770.142)
To locate the events within the <div> with class name rps-wrapper as the desired element is within an <frame> so you have to:
Induce WebDriverWait for the desired frame to be available and switch to it.
Induce WebDriverWait for the desired element to be clickable.
You can use either ofthe following Locator Strategies:
Using CSS_SELECTOR:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.TAG_NAME,"frame")))
rps_wrapper = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.rps-wrapper>ul#events")))
Using XPATH:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.TAG_NAME,"frame")))
rps_wrapper = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//div[#class='rps-wrapper']/ul[#id='events']")))
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
Here you can find a relevant discussion on Ways to deal with #document under iframe

How to click the close button within a modal window through Selenium and Python

Cannot click button id="close in modal window.
Trying all xpaths like:
//button[#data-dismiss='modal']
//button[#id='close'], //button[#type='button']
//button[contains(.,'Закрыть')]
//button[contains(#data-dismiss,'modal')]
//button[contains(#id,'close')]
Also trying to combine xpaths, but still not working
Code:
<div id="idCardGroupChangeStatusResult" class="modal fade in" tabindex="-1" role="dialog" aria-hidden="false" style="display: block;">
<div class="modal-dialog st-modal-dialog" style="width: 600px; padding-top: 250px;">
<div class="modal-content">
<div class="modal-header st-pad-normal">
<div class="modal-body">
<div class="modal-footer">
<button id="close" class="btn btn-default btn-sm" type="button" data-dismiss="modal"> Закрыть </button>
</div>
</div>
</div>
</div>
Css not working to
Any ideas?
As the element with text as Закрыть is within a Modal Dialog Box so to locate the desired element you have to induce WebDriverWait for the element to be clickable and you can use either of the following solutions:
Using CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.btn.btn-default.btn-sm#close[data-dismiss='modal']"))).click()
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#class='btn btn-default btn-sm' and #id='close'][#data-dismiss='modal']"))).click()
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
If element_to_be_clickable not works, try code below to check if there's more than one close buttons on the page. You can use code below to filter by visible or visible and latest one and click on it.
close_buttons = WebDriverWait(driver, 5).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#idCardGroupChangeStatusResult #close")))
# check how many buttons in on the HTML, you can try "visibility_of_all_elements_located"
print(len(close_buttons))
visible_buttons = [close_button for close_button in close_buttons if close_button.is_displayed()]
visible_buttons_len = len(visible_buttons)
print(visible_buttons_len)
visible_buttons[visible_buttons_len - 1].click()
Does the message disappears?
Update, message window disappear:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 5)
actions = ActionChains(driver)
#...
status_message = wait.until(
EC.visibility_of_element_located((By.CSS_SELECTOR, "#idCardGroupChangeStatusResult")))
actions.move_to_element(status_message).perform()
# here you can get text from message window, check/assert ..
status_message.find_element_by_css_selector("#close").click()

how to click button using find_element_by_xpath with inner html in selenium webdriver python3.7

first_click_content = driver.find_element_by_xpath("//div[#class='recent-report-wrapper']/div[2]/div/div[6]/div[2]")
print(first_click_content.get_attribute('innerHTML')
The above code give the result like this:
<button class="buttonWhite js-report-rerun">Re-run</button>
<button class="buttonWhite marginLeft js-report-edit">Edit</button>
<button class="buttonWhite marginLeft js-report-remove">Remove</button>
<button class="buttonWhite marginLeft js-report-save" style="display: none;">Save </button>
<button class="buttonWhite marginLeft js-report-view-errors" style="display: none;">View Errors</button>
<button class="buttonReportGreen marginLeft js-report-view" style="display: none;">View</button>
<button class="buttonReportGreen marginLeft js-report-download" style="display: inline-block;">Download</button>
I want to click the first button, how can I do that?
As the all the buttons are JavaScript enabled element you need to induce WebDriverwait for the desired element to be clickable and you can use either of the following solutions:
CSS_SELECTOR:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button.buttonWhite.js-report-rerun"))).click()
XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//button[#class='buttonWhite js-report-rerun' and contains(.,'Re-run')]"))).click()
Note : You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC

Categories

Resources