Weird thing with selenium test (python) on angular js based UI - python

We are testing a web application based on angular js. I have encountered it twice now. this time I need to click a dropdown embedded in a link tag . I can manually manipulate it with ipython, but once it run in script, the dropdown popup will not appear as what I can do it with the terminal.
Do you have any idea about this?

Judging from your comment "there is no error actually, the element is clicked", then I would suspect that the script is running fast enough to click the element before the JavaScript actions have been bound to the event. You can verify this by adding a
import time
time.sleep(4)
If the action works when there is a deliberate pause then you can be quite sure that it is a race condition between the JavaScript being bound and Selenium clicking the element.
How you deal with this is up to you. You could mark the DOM in some way when the events had been bound. That's a technique I've used in the past.
You could execute a bit of JavaScript in a loop that returned some information about the global state of the page, and use that to decide when the page was ready to interact with.

Related

Selenium Grid + Python: clicking on a WebElement results very slow

I have built a bot that plays an online roulette with Selenium (Selenium Grid) and Python.
When it comes to clicking on the number I want to bet on, it is extremely slow and does not manage to complete its stake (within the given time range for the bet) across all numbers that make my bet complete.
It seems like slowness may be given from the animation the button does after I click on it.
The code is very simple:
element = WebDriverWait(driver, timeout).until(EC.presence_of_element_located((By.XPATH, path)) # I manage to retrieve the WebElement, this is fast, no problem here
element.click() # this is slow
Here you can find:
how it looks now > https://drive.google.com/file/d/1dEuWTtrXHzRfXXVHhUbdNR8XtgMeWdU-/view?usp=sharing
my target > https://drive.google.com/file/d/1NUbr6rpOGjdMuClD5hby91jPVumqwLC5/view?usp=sharing (here I use the pynput library which is not my target cause I want the script to run on the server using Selenium Grid).
Anyone can help?
I'm not actually sure, is it the same problem or not. In my case, after clicking submit button on login form and redirecting to home page, my script doesn't do anything for around 4 minutes.
I've noticed, that WebElement.click() function ends execution only after page stops loading, but some trackers on site prevent page from complete loading, so I added uBlock extension and got rid of my problem.

Wait for an element to appear, instead of keeping on refreshing the page using selenium

I am using selenium webdriver, python to write a test case wherein I have to perform an action when a button appears on the screen. The tricky part over here is that if the button is not already present, I have to keep on refreshing the page till it comes and then perform the necessary actions.
I wanted to know if there's any other way around this so that I won't have to keep on refreshing the page?
Thank you for the help.

How can I click "invisible" reCAPTCHA buttons using Selenium web automation?

I am using Python and Selenium to automate this website: https://prenotami.esteri.it
The script I made fills out a form and then clicks a button to advance to the next page. These actions are carried out using Selenium's find_element_by_xpath() function. Recently, the website added a reCAPTCHA that pops up after the button is clicked, and must be completed before advancing.
I have already written a Python script that is capable of surpassing this type of captchas by using the audio option. However, in this particular website, I am not able to find the xpath to the audio button of the reCAPTCHA. Although there is an iframe that contains the reCAPTCHA, there seems not to be anything inside it.
In the first attached image you can see how this website's reCAPTCHA looks like in HTML, compared to other website that is visible in the second image, where a #document can be seen inside the iframe.
My intention is to run this program using headless Chrome, so I can't relay in any mouse control functions offered by pyautogui for example.
I've been scratching my head around this problem for a while, so any advice is useful. Thanks!
Edit: after some research I have found that this type of reCAPTCHA that doesn't need to check a "I am not a robot" checkbox is called "invisible reCAPTCHA". The captcha only pops up if the detected activity is suspicious (for example clicking too fast). I have tried adding random waits and movements to mimic human behaviour, but the captcha still appears after some tries. Since I don't think there is a way to avoid the captcha from appearing 100% of the times, the question of how to click the buttons using Selenium's find_element_by_xpath() function remains the same. Leaving this as a note just in case someone finds it useful.
Ever tried to use the following function:
add_argument("-auto-open-devtools-for-tabs")
I managed to interact with captcha
If the position is always fixed, you can use PyAutoGUI to move the mouse and click on it
import pyautogui
pyautogui.click(100, 100) # button coordinates
Since, it is in iframe, we need to move our selenium pointing to iframe and then use your xpath.
driver.switch_to.frame("c-la7g7xqfbit4")
capchaBtn = driver.find_element_by_xpath("(//button[#id='recaptcha-audio-button'])[2]")

Selenium in Python doesn't recognise changes in the DOM even after waiting

I'm using selenium on a Python script to get some data and execute some scripts on a javascript/ajax rendered website, which means some buttons or scripts will change the DOM without loading a new page or changing the URL.
The situation is: as soon as the page is loaded, I execute the following script:
driver1.execute_script("javascript:changeOption('a', 'b','otherPage.html');")
changeOption is a script written directly inside the script tags of the HTML. It works, and the script will cause the DOM to change.
Now, the DOM has changed and there are new scripts written directly on the HTML, which I can clearly see inside Chrome's inspector "Elements" tab. I wait some seconds and try to run one of the new scripts:
driver1.execute_script("javascript:filterOption(0);")
And I get an error! It says this script 'filterOption' doesn't exist.
After some investigation, I notice selenium isn't recognising that the DOM has changed and that there are new elements and scripts inside the page! That's why it says the new script doesn't exist.
What I've tried so far:
Implicit and explicit waits. Neither worked.
time.sleep(), with several seconds, before executing the second script. Didn't work either.
Forcibly try to execute the script with "try...except" statement inside a while loop. Never works, always goes to the exception.
Checked whether the page selenium is 'seeing' is the updated page, by executing again the first script, checking for some elements, waiting for new elements to appear etc. No, it isn't: selenium really hasn't noticed the DOM was updated, that's for sure.
I did some research here and on the documentation looking for some way to force selenium to read the DOM again without refreshing the page, because refreshing would cause it to go back to the very first page and lose all the changes. It looks like there is no way to do it and every single answer I found was different and didn't work.
Do you have any suggestions of what I could do so Selenium will notice there are new scripts on the DOM?
Thank you!
P.S: I'm using the latest selenium with Python 3 and Chrome.
SOLVED!
It turns out the new code is rendered inside an iFrame, that's why selenium couldn't see it before.

Handle random ForeSee popup using Python and Selenium

I'm new to coding and trying to use Selenium with Python to click through a website and fill a shopping cart. I've got things working well except for the random ForeSee survey popup. When it appears (and it doesn't always appear in the same location), my code stops working at that point.
I read the ForeSee documentation and it says "...when the invitation is displayed, the fsr.r...cookie is dropped. This cookie prevents a user from being invited again for X days (default 90)."
Hoping for a quick fix, I created a separate Firefox profile and ran through the website and got the ForeSee pop up invitation--no more pop up when manually using that profile. But I still get the pop up when using Selenium.
I used this code:
fp = webdriver.FirefoxProfile('C:\path\to\profile')
browser = webdriver.Firefox(firefox_profile=fp)
EDIT: I got the cookie working. I was using the Local folder instead of the Roaming folder in C:\path\to\profile. Using the roaming folder solved the problem.
My question edited to delete the part about the cookie not working:
Can someone suggest code to permanently handle the ForeSee pop up that appears randomly and on random pages?
I'm using using Protractor with JS, so I can't give you actual code to handle the issue, but I can give you an idea how to approach this.
In a nutshell
When following script is executed in the browser's console -
window.FSR.setFSRVisibility(true);
it makes ForeSee popup appear behind the rest of HTML elements. And doesn't affect UI tests anymore
So my protractor script will look like so
await browser.executeScript(
`window.FSR.setFSRVisibility(true);`
);
Theory
So ForeSee is one of those services that can be integrated with any web app, and will be pulling js code from their API and changing HTML of your app, by executing the code on the scope of the website. Another example of such company is walkme
Obviously in modern world, if these guys can overlay a webpage, they should have a configuration to make it optional (at least for lower environments) and they actually do. What I mentioned as a solution came from this page. But assuming they didn't have such option, one could reach out their support and ask how to workaround their popups. Even if they didn't have such option they would gladly consider it as a feature for improvement.

Categories