WebDriver python equivalent of "refreshed" expected condition - python

So, using WebDriver python binding, I came across a problem that I need to wait until an element is refreshed on the page. Say, I have two radio buttons, and by clicking either of them, a label text is changed.
Currently, if I click on one and get the text and then click on the other and get the text again, I will get the same text although it has changed. Thus, I think I need to wait for the element to be refreshed.
On Java documentation, there is a refreshed expected condition which appears to be useful in this case. But I'm unable to find the python version of it. What is its equivalent? How can I workaround this?

text_to_be_present_in_element() under expected_conditions.py is similar to what you're looking for. If it's not the value that's changing but instead another field like textContent, you could roll a custom solution which is similar to text_to_be_present_in_element().
def attribute_text_is_in_element(text, locator, attribute):
try:
element_text = driver.find_element(locator).get_attribute(attribute)
if text == element_text:
return True
else:
return False
except StaleElementReferenceException:
return False

Related

Python Selenium, Input field returns an ElementNotInteractableException even though element is interactable

SOLVED:
It seems like this single input field would be not interactable unless it was clicked in the most recent 0.1 seconds. To solve that the following code was used:
ActionChains(self.driver).move_to_element(input).click().send_keys("200").perform()
This way the focus stays on the element and the input works. Interestingly, if input.send_keys() is called this still does not work.
Problem:
After pressing a button on the website, a popup window opens up which contains multiple input fields which are generated by react. Most of these are accessible. However, one of them is not and returns an ElementNotInteractableException error. I have tried the most common solutions but those do not work.
The interesting part is that when the element is accessed manually from the front end, it can be interacted with. The element also is shown normally in a screenshot which is taken upon an exception being thrown
Solutions tried:
Increase implicit wait until 1 minute,
Add explicit wait untill 1 minute
Use different finding methods for the element
Reorder test to see if other elements influence it (all possible orders have failed)
Add Actionchains Move to and Click. The move to and click work (I can see the element being selected with a blue outline, but the input still feels)
Use Javascript to insert the string into the input fields.value
Code block on which the error occurs:
#this input element is next to it in the same parent element
dropdownparent = elems[2].find_element_by_xpath(".//div[#role='combobox']")
dropdowninput = dropdownparent.find_element_by_css_selector("input")
f.inputtext(dropdowninput, "Coulance", True )
#reobtain the parent items to avoid a stale element reference error
modal = self.driver.find_element_by_class_name("component-window")
body = modal.find_element_by_class_name("body")
elems = body.find_elements_by_xpath("./div")
required = elems[2].find_elements_by_class_name("required")
inputparent = required[1].find_element_by_class_name("input")
input = inputparent.find_element_by_css_selector("input")
#error occurs on next line
f.inputtext(input, "200")
Error log:
https://pastebin.com/ihqCvjfj
its long but its a very standard elementnotaccessible
Any suggestions would be appreciated, I will update the solutions tried section whenever I try something
Element not interactable comes when the element is out of clickable area or some other element is covering up that element.
You can try by scrolling the page to an element or you can set input value by executing javascript, something like this:
element = inputparent.find_element_by_css_selector("input")
driver.execute_script("""arguments[0].value = arguments[1];""", element, "some input value")

Setting value for input element in selenium Python

I am trying to change the value of an input tag element.
Here is the tag: <input type="hidden" id="hiRequestAccessType" data-bind="value: requestAccessTypeStr" value="2">
I want to change value to "2,1".
Based on discussion at Set value of input instead of sendKeys() - selenium webdriver nodejs, I tried using execute_script, but value remains unchanged.
I tried this:
passwordcheck_input_element = driver.find_element_by_xpath('//*[#id="hiRequestAccessType"]') . ###THIS DOESNT THROW ERRORS
new_value = "2,1"
driver.execute_script("arguments[0].value = arguments[1].toString()", passwordcheck_input_element, new_value)
# driver.execute_script("arguments[0].value = '" + new_value + "'", passwordcheck_input_element) . ###TRIED THIS IN LIEU OF ABOVE
For either alternative, code runs but value remains unchanged from visual inspection. I also tried the above two alternatives using 'setAttribute' instead of directly, same (no change) result.
Note that the webpage is a form where clicking on a check box changes value to "2,1" as desired. (But if I try finding the check box element, I get the message it is not clickable, hence this route).
Now, what's weird is I know it's doing something right behind the scenes because I tried querying value attribute before and after my execute_script call and it prints out the new value correctly for latter. However, as I said, the UI doesnt show this change; further, when I move on and hit the submit buttom further down, it's the old value that gets used because I am not getting the page that should load if the new value were used.
Could you please try the code below?
passwordcheck_input_element = driver.find_element_by_id("hiRequestAccessType")
driver.execute_script("arguments[0].value = '2,1';", passwordcheck_input_element)
You can also control the checkbox object via javascript execution if it is not clickable.
driver.execute_script("document.getElementById('hiRequestAccessType').checked = true;")
driver.find_element_by_xpath('//*[#id="hiRequestAccessType"]').setAttribute("value", "1")
Short you can select with xpath or css name element after selection you can change with .setAttribute function your value. Also you can get current selected element value with getAttribute function.For simulate checkbox click : .setAttribute("checked", "checked")

Advice on working three three iframes and switching back and forth

I am currently working on a project where I have to switch between multiple iframes after every step and it is getting hard for me to maintain reusable functions. Every other step can have a different Iframe.
I tried using try and except for Iframes but I do not think it is a good idea.
So I have something like this before clicking on any button. Note - there can be a situation where there are no Iframes.
try:
self.switchToFrame(*MainPageLocatars.FRAMEONE)
self.switchToFrame(*MainPageLocatars.SUBLISTFRAME)
except:
pass
try:
self.switchToFrame(*MainPageLocatars.FRAMEONE)
except:
pass
Is it possible to change it something like this? and define it in a function and just call the function and it will change to the proper frame?
WebElement frame = driver.findElement(By.Id("frame1"));
// or
WebElement frame = driver.findElement(By.Id("frame2"));
// or
WebElement frame = driver.findElement(By.Id("frame3"))
//Now we will switch focus,
driver.switchTo().frame("frame");

Selenium Python document.getElementsByClassName()

I'm using Selenium with Python3 to automate entering data into a website.
I have tried looking everywhere for how to deal with selecting an element by class if there is more than one but I can't figure out how to select the accordion-toggle[1]. Nothing happens on selenium but it works fine on any browser. Also, is there any way to just use the regular javascript or jquery commands?:
accordion=find_element_by_class("accordion-toggle"[1])
accordion.click()
#otheraccordion=find_element_by_css_selector("#AdvancedAddress > div.accordion-heading.in > div.accordion-toggle > span.accordionExpandCollapse")
#otheraccordion.click()
StreetNameField=driver.find_element_by_id("Advanced_FindMyParcel_PropertyStreetName")
StreetNameField.send_keys("Sherman")
ZipField=driver.find_element_by_id("Advanced_FindMyParcel_PropertyZip")
ZipField.send_keys("90201")
ZipButton=driver.find_element_by_id("btnSearchFindMyParcels")
ZipButton.click()
You actually can use document.getElementsByClassName() through execute_script() call:
driver.execute_script("document.getElementsByClassName('accordion-toggle')[0].click();")
But I would not go down to executing javascript for such a simple task. Easier to locate the element using find_element_by_class_name():
accordion = driver.find_element_by_class_name('accordion-toggle')
accordion.click()
You are looking for find_element(s)_by_css_selector - reference here - use the css prefix '.classname` to indicate the class.
e.g. to find
<div class='theClass'>
driver.find_elements_by_css_selector('.theClass')
You can also use the By syntax:
driver.find_elements(By.CSS_SELECTOR, '.theClass')
Edit
It seems the problem may be more to Clicking the element, rather than finding it.
Ensure the element is visible
For Chrome, you may need to mimic hovering the mouse over the element before clicking this - see Actions / ActionChains MoveToElement to hover over the element.
For IE, you may need to ensure the browser / frame gets the focus, prior to the element Click - you may need to apply a hack like one of these.
In addition to #alecxe response, I would also suggest using the function find_elements_by_class_name instead of find_element_by_class_name in case there are multiple elements with the same class name.
accordion = driver.find_elements_by_class_name('accordion-toggle')[1] # Selects second element
accordion.click()
Using find_element_by_class_name will return only the first element with that class name.

Selenium selected option in dropdown not displayed correctly

I have the following issue with Selenium Webdriver. There are two dropdown menus on a page i am testing "brand" and "items". The options of "items" depend on which brand you choose. I am trying to iterate through all possible choices and print brand-item pairs. I use two possible ways to pick an option from each dropdown menu
Using Select():
def retryingSelectOption(name,n):
result=False
attempts=0
while attempts<5:
try:
element=Select(driver.find_element_by_name(name))
element.select_by_index(n)
print element.all_selected_options[0].text
result=True
break
except StaleElementReferenceException:
pass
attempts+=1
return result
And using .click():
def retryingClickOption(name,n):
result=False
attempts=0
while attempts<5:
try:
driver.find_element_by_name(name).find_elements_by_tag_name("option")[n].click()
result=True
break
except StaleElementReferenceException:
pass
attempts+=1
return result
My problem is that at ,what seem to me as random moments (sometimes it works sometimes it does not), even though the above functions return True and printing out the selected option shows me the correct answer, the browser still displays the previous option. So basically Selenium tells me i have picked the right option but the browser displays the previous one.No idea what is wrong.
After checking it a bit more it seems that if i manually click somewhere in the browser the option actually refreshes to the correct value. It seems like the browser hangs.

Categories

Resources