Selenium webdriver can't find visible element - python

I have a problem with finding element on a webpage. It's a popup window with a confirmation [NO]/[YES]. Selenium can find a parent of a buttons but not a button itself.
Popup window view
HTML block of code:
<div tabindex="-1" role="alertdialog" style="position: fixed; height: auto; width: 300px; top: 188.5px; left: 800px; max-width: 100%;"
class="ui-dialog ui-dialog--notification ui-dialog--modern ui-widget ui-widget-content ui-front ui-dialog-buttons ui-draggable"
aria-describedby="ui-id-3" aria-labelledby="ui-id-4">
<div class="ui-dialog-titlebar ui-corner-all ui-widget-header ui-helper-clearfix ui-draggable-handle"></div>
<div class="ui-dialog-content ui-widget-content" style="width: auto; min-height: 0px; max-height: none; height: 32px;">
<div class="a-AlertMessage">
<div class="a-AlertMessage-body">
<div class="a-AlertMessage-details" id="ui-id-3">Czy chcesz wygenerować pozycje dla całej dostawy?</div>
</div>
</div>
</div>
<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"><div
class="ui-dialog-buttonset">
<button type="button" class="ui-button ui-corner-all ui-widget">Nie</button>
<button type="button" class="js-confirmBtn ui-button ui-corner-all ui-widget ui-button--hot">Tak</button>
</div>
</div>
</div>
Here is a code snippet that selenium can't find and gives an error 'Unable to locate element':
pop_up_yes_button = driver.find_element(By.XPATH, '//*[#id="t_PageBody"]/div[15]/div[3]/div/button[2]').click()
Parent is avaible for selenium without a problem:
driver.find_element(By.XPATH, '//*[#id="t_PageBody"]/div[15]')
I also tried WebDriverWait and ExpectedConditions but it gives TimeoutException:
WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.XPATH, '//*[#id="t_PageBody"]/div[15]/div[3]/div/button[2]'))).click()

As you said that it is a popup window, it is very likely that the button is in an iFrame. You have to wait until the iFrame loads and then search the element again.
Luckily, selenium has a built in function for dealing with iFrames:
your_button = WebDriverWait(driver,
20).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,'//*[#id="t_PageBody"]/div[15]/div[3]/div/button[2]')))
your_button.click()
Don't just copy and paste this code, understand this thing and implement it.

Related

Why cant I find the element of credit card number using selenium?

I am trying to make an automated checkout system but I can't seem to send keys in fields of this payment box. Even when I try implicit wait and wait for it to load in it still doesn't work.
checkout = driver.find_element_by_id("number")
checkout.send_keys("9848432")
<input required="" autocomplete="cc-number" id="number" name="number" type="tel" aria-describedby="error-for-number tooltip-for-number" data-current-field="number" placeholder="Card number" style="font-family: Roboto, sans-serif; padding: 0.94em 0.8em; transition: padding 0.2s ease-out 0s;">
Here's a link!
Here is the URL you need to fill in the info until you get to the payment page, which is where I am having the issues
It might be in a nested iframe. A similar checkout due to not proper reproducible code.
<iframe src="https://fs.global-e.com/Checkout/v2/598d87e9-cd85-4f61-84df-81e345d62f05?gaSesID=526107767.603750114.583&gaMerchantClientInfo=undefined#undefined&chkcuid=b51f4449-13e2-4883-92ba-2641bb06ec51&isNECAllowed=true&vph=663&ift=87" class="Intrnl_CO_Container" id="Intrnl_CO_Container" name="Intrnl_CO_Container" allowtransparency="true" width="100%" scrolling="no" marginheight="0" marginwidth="0" frameborder="0" height="1000px" style="height: 3101px;">
<iframe id="secureWindow" class="clear-fix clearfix" allowtransparency="true" style="width: 100%; min-height: 160px; height: 165px;" src="https://securev2.global-e.com/payments/CreditCardForm/598d87e9-cd85-4f61-84df-81e345d62f05/11">
<input autocomplete="off" class="form-control input-validation-error" data-type="unknown" data-type-id="1" data-val="true" data-val-luhn="Card number not valid" data-val-luhn-allowempty="False" data-val-luhn-allowspaces="False" data-val-required="Card number" id="cardNum" name="PaymentData.cardNum" pattern="[0-9]{13,16}" placeholder="Card number" type="tel" value="">
</iframe>
</iframe>
Which was solved with:
wait = WebDriverWait(driver, 10)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'Intrnl_CO_Container')))
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, 'secureWindow')))
checkout = wait.until(EC.presence_of_element_located((By.ID, "cardNum")))
checkout.send_keys("9848432")
Import
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

seleniumpython dropdown list div

i whould like to select the element "aout" for example on the folloing dropdown list with python selenium
<div class="questionDropdownContainer inlineBlock isActive" id="dob2_m">
<span class="questionDropdownPlaceholder" data-val="3" id="dateMonth" style="color: rgb(0, 0, 0);">mars</span>
<span class="iconDropdown inlineBlock valignMiddle"></span>
<div class="questionDropdownOptions ps-container ps-active-x ps-active-y isActiveSurveyDropDown" style="display: block; overflow: hidden;">
<span class="option-1-month" data-id="1">janvier</span>
<span class="option-1-month" data-id="2">février</span>
<span class="option-1-month selected" data-id="3">mars</span>
<span class="option-1-month" data-id="4">avril</span>
<span class="option-1-month" data-id="5">mai</span>
<span class="option-1-month" data-id="6">juin</span>
<span class="option-1-month" data-id="7">juillet</span>
<span class="option-1-month" data-id="8">août</span>
<span class="option-1-month" data-id="9">septembre</span>
<span class="option-1-month" data-id="10">octobre</span>
<span class="option-1-month" data-id="11">novembre</span>
<span class="option-1-month" data-id="12">décembre</span>
<div class="ps-scrollbar-x-rail" style="width: 120px; left: 0px; bottom: 3px;"><div class="ps-scrollbar-x" style="left: 0px; width: 110px;"></div></div><div class="ps-scrollbar-y-rail" style="top: 0px; height: 234px; right: 3px;"><div class="ps-scrollbar-y" style="top: 0px; height: 116px;"></div></div></div>
<input type="hidden" name="date_m" value="4">
</div>
When I try this code…
driver.find_element_by_id("dob2_m").click()
driver.find_element_by_id("dob2_m").find_element_by_xpath('//*[#data-id="8"]').click()
I get this error…
error script picture
How to do it ?
Help me please
Thank you
The error snippet clearly says the error occurs when webdriver tries to interact with element with class="option-1-day". But this element is not present in the code you have shared. So i assume, you are facing issue while trying to select date from dropdown.
1.Before clicking dropdown element, try to add wait statement
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))
2. It will occur when the webelement you trying to click, located at end of dropdown. So it can only clickable once scrolling it down.
Actions action = new Actions(driver);
action.moveToElement(element);
Use select class for handling dropdown.
s1= Select(driver.find_element_by_id('id_of_your_element'))//in this case it would be dob2_m
s1.select_by_visible_text('janvier')
Ignore formatting using mobile to answer.
Option 2
Use javascriptexecutor to scroll and click on element
ele= self.web_driver.find_element_by_xpath('SOME_XPATH')
coordinates = ele.location_once_scrolled_into_view
self.web_driver.execute_script('window.scrollTo({}, {});'.format(coordinates['x'], coordinates
You have to use ActionChains.
When you call methods for actions on the ActionChains object, the actions are stored in a queue in the ActionChains object. When you call perform(), the events are fired in the order they are queued up.
More information.
Here is an example:
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.ui import Select
...#navigate to page
el=driver.find_element_by_id("bxFormPesquisa") #here I get the dropdown element
ActionChains(driver).click(el).perform()
select = Select(driver.find_element_by_name('bxFormPesquisa')) #again
select.select_by_visible_text('AL') #it is the text in dropdown list
#dropdown should be selected with value from line above

Use selenium to write in and run a code cell in jupyterlab

I would like to test a patched implementation of juptyerlab. I was hoping to use selenium to execute "hello world" in a code cell. So far I can log in and create a new notebook:
from selenium import webdriver
driver = webdriver.Firefox()
# assume jupyterlab is running and serving on localhost at port 8888
driver.get("http://localhost:8888")
elem = driver.find_element_by_id("password_input")
password = ""
elem.send_keys(password)
elem = driver.find_element_by_id("login_submit")
elem.click()
elem = driver.find_element_by_css_selector(".jp-Launcher-cwd+ .jp-Launcher-section .jp-LauncherCard")
elem.click()
This creates a new notebook, but now I'm stuck at the point of entering some code in a cell and running it. If I view the page source I don't see any html elements for the cells. But if I enter print("test") in a cell, then driver.page_source contains this (it's pretty nested in other stuff I've omitted too):
<div class="CodeMirror cm-s-jupyter CodeMirror-wrap jp-mod-readOnly">
<div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 0px; left: 0px;">
<textarea
style="position: absolute; bottom: -1em; padding: 0px; width: 1px; height: 1em; outline: currentcolor none medium;"
autocorrect="off" autocapitalize="off"
spellcheck="false" tabindex="0"
wrap="off"></textarea></div>
<div class="CodeMirror-vscrollbar" tabindex="-1"
cm-not-content="true"
style="display: block; bottom: 0px;">
<div style="min-width: 1px; height: 33px;"></div>
</div>
<div class="CodeMirror-hscrollbar" tabindex="-1"
cm-not-content="true">
<div style="height: 100%; min-height: 1px; width: 0px;"></div>
</div>
<div class="CodeMirror-scrollbar-filler"
cm-not-content="true"></div>
<div class="CodeMirror-gutter-filler"
cm-not-content="true"></div>
<div class="CodeMirror-scroll" tabindex="-1" draggable="true">
<div class="CodeMirror-sizer"
style="margin-left: 0px; padding-right: 0px; padding-bottom: 0px;">
<div style="position: relative;">
<div class="CodeMirror-lines" role="presentation">
<div style="position: relative; outline: currentcolor none medium;"
role="presentation">
<div class="CodeMirror-measure">
<pre><span>xxxxxxxxxx</span></pre>
</div>
<div class="CodeMirror-measure">
<pre class="CodeMirror-line"
role="presentation"><span
role="presentation"><span
class="cm-builtin">print</span>(<span
class="cm-string">"test"</span>)</span></pre>
</div>
<div style="position: relative; z-index: 1;"></div>
<div class="CodeMirror-cursors"></div>
<div class="CodeMirror-code"
role="presentation"></div>
</div>
</div>
</div>
</div>
<div style="position: absolute; height: 30px; width: 1px; border-bottom: 0px solid transparent;"></div>
<div class="CodeMirror-gutters"
style="display: none;"></div>
</div>
</div>
I can see where the text for print("text") is (i.e. the deepest nested elements in the above html snippet), but I can't figure out which element here I would be able to send text to or send keys to.
I came across robotframework-jupyterlibrary and it has some clues such as this and this . From those links I see
${JLAB CSS ACTIVE INPUT} ${JLAB CSS ACTIVE CELL} .CodeMirror
and
Add and Run JupyterLab Code Cell
[Arguments] ${code}=print("hello world")
[Documentation] Add a ``code`` cell to the currently active notebook and run it.
Click Element css:${JLAB CSS NB TOOLBAR} ${JLAB CSS ICON ADD}
Sleep 0.1s
${cell} = Get WebElement css:${JLAB CSS ACTIVE INPUT}
Click Element ${cell}
Set CodeMirror Value ${JLAB CSS ACTIVE INPUT} ${code}
Run Current JupyterLab Code Cell
Click Element ${cell}
which makes me think if I select the .CodeMirror element, then I just need to figure out what Get WebElement does in that weird language and how to do it in selenium.
Any ideas?
I've also tried (based on https://stackoverflow.com/a/48723135/1011724 and https://stackoverflow.com/a/50279295/1011724):
from selenium.webdriver.common.action_chains import ActionChains
actions = action_chains.ActionChains(driver)
textarea = driver.find_elements_by_css_selector('.CodeMirror textarea')[0] # tried for [0], [1] ,[2] and [3] which is all of them.
actions.move_to_element(textarea).click().send_keys("testing...").perform()
but I keep getting the error
selenium.common.exceptions.WebDriverException: Message: TypeError: rect is undefined
Code below tested with Chrome, Firefox and jupyterlab latest versions:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
wait = WebDriverWait(driver, 10)
driver.get("http://localhost:8888")
token = "0107216930d05db8a7c36ad6a73573dd5349c3dd56fee852"
wait.until(EC.element_to_be_clickable((By.ID, "password_input"))).send_keys(token, Keys.ENTER)
# wait for "Python 3" Notebook menu or CodeMirror element if already launched.
wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR, "[title='Python 3'][data-category='Notebook'], .jp-Notebook .CodeMirror")))
# if "Python 3" Notebook menu found click to open new Notebook
if len(driver.find_elements_by_css_selector("[title='Python 3'][data-category='Notebook']")) > 0:
driver.find_element_by_css_selector("[title='Python 3'][data-category='Notebook']").click()
# wait for CodeMirror and click to focus
code_mirror = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".jp-Notebook .CodeMirror")))
code_mirror.click()
code_mirror.find_element_by_tag_name("textarea").send_keys("print('Hello World!')")
driver.find_element_by_css_selector("[data-icon='run']").click()
output = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".jp-OutputArea-output")))
print(output.text)
assert output.text.strip() == "Hello World!"
driver.quit()
To Open Jupyter-Notebook:
Either Open a command window and navigate to the repository folder or Open anaconda-command-prompt window and simply execute
jupyter notebook --NotebookApp.token='' --NotebookApp.password=''
After loading notebook using driver.get("http://localhost:8888"), Here is the most tricky part, that how to select a Dynamically changing object. Visit Reference: Dynamically Changing IDs.
By using find_element_by_xpath
By using find_element_by_css_selector
These both will give you the same selection-point but it would be better to use Xpath which is more convenient technique. You can move forward like this;
import time
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
driver = webdriver.Chrome('chromedriver.exe')
wait = WebDriverWait(driver, 20)
driver.maximize_window()
website_url = "http://localhost:8888/"
driver.get(website_url)
# Using Xpath
# I prefer using xpath, because it is simple to understand
# and if you want to dynamically enter data into fields, it would be an awesome approach
driver.find_element_by_xpath("//div[#id='new-buttons']").click()
if len(driver.find_elements_by_xpath("//div[#id='new-buttons']//li[#id='kernel-python3']")) > 0:
time.sleep(3)
driver.find_element_by_xpath("//div[#id='new-buttons']//li[#id='kernel-python3']").click()
driver.find_element_by_xpath('//div[#class="cell code_cell rendered selected"]').click()
# Using css_selector
#driver.find_element_by_css_selector("#notebook-container > div").click()
command = 'print("Hello World!")'
#a = driver.find_element_by_css_selector("#notebook-container > div > div.input > div.inner_cell >"
# "div.input_area > div > div:nth-child(1) > textarea")
time.sleep(3)
# To select Note-Book text-area and place command in it.
a = driver.find_element_by_xpath('//div[#class="input_area"]//textarea').click().send_keys(command)
# To run the Code in Selected Cell
time.sleep(3)
driver.find_element_by_xpath("//button[#title='Run']").click()
print("Test is done.")

How to locate the upload button related to the text Upload Image as per the HTML?

I'm using Selenium with Firefox (I've tried chrome but the success ratio on this one was significantly lower). I'm trying to locate an element (upload button) and the success ratio is nowhere near an acceptable percentage.
Now I know that I could try to use just selenium to the input but it wont locate it as well no matter what I do. So I used AutoIt for the uploading part.
frdriver.get('')
time.sleep(11)
try:
# el = WebDriverWait(frdriver, 15).until(EC.presence_of_element_located((By.XPATH, '/html/body/div[1]/header/div[2]/div[2]/div/div/form/i[2]')))
el = frdriver.find_element_by_xpath('/html/body/div[1]/header/div[2]/div[2]/div/div/form/i[2]')
try:
el.click()
print(el)
#ActionChains(frdriver).move_to_element(el).click().perform()
try:
#element = WebDriverWait(frdriver, 15).until(EC.presence_of_element_located((By.XPATH, '/html/body/div[1]/header/div[2]/div[2]/div/div/form/div[2]/div[3]/div[1]/div/div/div[1]')))
element = frdriver.find_element_by_xpath('/html/body/div[1]/header/div[2]/div[2]/div/div/form/div[2]/div[3]/div[1]/div/div/div[1]')
time.sleep(4)
try:
element.click()
#ActionChains(frdriver).move_to_element(element).click().perform()
autoit.run("/image.exe")
r = 100
except:
print('Firefox retries upload')
r += 1
except:
print('Firefox retries upload')
r += 1
except:
print('Firefox retries upload')
r += 1
except:
print('Firefox retries upload')
r += 1
As you can see I've tried many ways, each one had almost the same success.
I'm using a remote windows machine for the job and it really might be my idea, but when it isn't minimized it works a lot better.
Also there is something else, for some reason there are times that even if it hasn't successfully clicked a button it bypasses the try/except and proceeds.
Edit html of the page
<div class="ui-searchbar-keyword-panel ui-searchbar-keyword-hide ui-searchbar-static" style="z-index: 99; position: absolute; left: 0px; top: 35px;" data-widget-cid="widget-7">
<div class="ui-searchbar-img-search-box">
<div class="icbu-w-image-uploader-panel">
<div class="icbu-w-image-uploader-content">
<div class="upload-btn-wrapper">
<div class="upload-btn" data-spm-anchor-id="a2700.8293689.scGlobalHomeHeader.i1.2ce265aarlKA3D" style="z-index: 1;">Upload Image</div>
<div id="html5_1cjiqdvveht51pom1nbkqoiaop3_container" class="moxie-shim moxie-shim-html5" style="position: absolute; top: 14px; left: 224px; width: 109px; height: 28px; overflow: hidden; z-index: 0;">
<input id="html5_1cjiqdvveht51pom1nbkqoiaop3" type="file" style="font-size: 999px; opacity: 0; position: absolute; top: 0px; left: 0px; width: 100%; height: 100%;" multiple="" accept="image/jpeg,image/png,image/bmp">
</div>
</div>
<div class="response-text">Max 2MB per Image</div>
</div>
</div>
</div>
<div class="J-box-loadding-mask box-loadding-mask" data-role="loading" style="display: none;">
<div class="mh-mamo-loadding-box">
<i class="mh-mamo-icon-loadding"></i>
<span class="J-loading-text mh-mamo-loadding-text">Loading...</span>
</div>
</div>
</div>
You should use driver.implicitly_wait(X) where X is a number of seconds instead of reinventing the wheel with using time.sleep and retrying. That will increase selenium's tolerance towards the page loading and you will have better success in finding page elements.
To locate the upload button related to the text Upload Image you can use the following solution:
XPATH:
upload_button = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[#class='upload-btn-wrapper']//div[#class='moxie-shim moxie-shim-html5' and starts-with(#id,'html5_')]/input[starts-with(#id,'html5_')]"))).click()
CSS_SELECTOR:
upload_button = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.upload-btn-wrapper div.moxie-shim.moxie-shim-html5[id^='html5_']>input[id^='html5_']"))).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

python + selenium button in div overlay clickable in testing but not when automated

<div class="t-window-content t-content" style="overflow: auto; width: 400px; height: 389.4px;">
<div id="frmSchTarget">
<form action="/Search/SearchTypePreName"
method="post" onclick="Sys.Mvc.AsyncForm.handleClick(this, new Sys.UI.DomEvent(event));"
onsubmit="Sys.Mvc.AsyncForm.handleSubmit(this, new Sys.UI.DomEvent(event), { insertionMode: Sys.Mvc.InsertionMode.replace, onBegin: Function.createDelegate(this, PreNameListWindow), onSuccess: Function.createDelegate(this, Form_OnSuccess) });"><input type="hidden" id="NameList"
name="NameList">
<div style="text-align: left; padding-left: 10px">
<span style="margin-right: 20px;">
<button id="TreeViewButtonCollapse" name="TreeViewButtonCollapse" onclick="ExpandCollapseTreeView('NameListTreeView', false); return false;" title="Collapse All">
<img src="/Content/Images/toggle_up.png">
</button>
<button id="TreeViewButtonExpand" name="TreeViewButtonExpand" onclick="ExpandCollapseTreeView('NameListTreeView', true); return false;" title="Expand All">
<img src="/Content/Images/toggle_down.png">
</button>
</span>
</div>
<div id="divSelectNamesArea" style="height: 325px; overflow: auto;">
"i removed a very large list from here"
</div>
<hr class="PopupLineStyle">
<div style="text-align: left; padding-left: 10px">
<span style="margin-right: 20px;"><input type="checkbox" id="Checkbox1" name="SelectAllPrenamesToggle" onclick="SelectAllOrNoneInTreeView('NameListTreeView', this.checked);">
All / None</span>
<input type="submit" class="t-button" value="Done"
onclick="GetNameListString('NameListTreeView');">
</div>
</form>
</div>
</div>
The above code has basically been the bane of my existence for about a week now. I am trying to run a webscraper and upon submitting a request a div overlay appears on the page. The code snippet above shows how the 'Done' button used to get rid of it is implemented.
In testing I am able to use
buttons = driver.find_elements_by_xpath('//input[contains(#class,"t-button")]')
to find all buttons present and then it is button [5], however once I automate this does not work.
I have also tried an implicit wait with the following xpath:
//*[#id="frmSchTarget"]/form/div[3]/input
This also is a no-go. Please help, I have been trying just about everything an searched through stackoverflow for over a week already. I just can't figure it out.
// wait 15s before click button for debug purpose, in case click button before
// it be rendered out on page
time.sleep(15)
button_done = driver.find_element_by_css_selector("#frmSchTarget input[value='Done']")
button_done.click()
if above code work, remove the time.sleep() and run again, if failed, it means
you need wait some moment before click it, please use explicit wait replace time.sleep()

Categories

Resources