4

I'm writing a Python (3.6.6) script that uses Selenium (3.141.0) to open a URL in Chrome (ChromeDriver version 77.0.3865.40), navigate a series of menus, enter login details into a popup and login. Here's my script:

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains

url = 'https://some.url.com/'

driver = webdriver.Chrome()
action = ActionChains(driver)
driver.get(url)

button_1 = driver.find_element_by_xpath("//*[contains(text(), 'button_1_text')]")
button_1.click()

button_2 = driver.find_element_by_id('button_2_text')
button_2 .click()

link = driver.find_element_by_link_text('link_text')
action.move_to_element(link).perform()
link.click()

alert_obj = driver.switch_to.alert

If I perform this navigation manually, I get a prompt asking for a username and password, with two buttons to sign in or cancel. When Selenium does it, I see the prompt flash up, but then quickly disappear, so I get the error:

selenium.common.exceptions.NoAlertPresentException: Message: no such alert

If I refresh the still open browser manually I can get the alert to appear, but if I script a refresh the prompt once again vanishes. I've tried putting a wait in for an alert to appear, as described in Check if any alert exists using selenium with python, but the wait just times out.

If I check the source code of the page that is left open once the alert has disappeared, I see this:

<!-- template name: form.autopost.template.html -->

<html>
    <head>
    <title>Submit Form</title>
    </head>
    <body onload="javascript:document.forms[0].submit()">
       <noscript>
            <p>
                <strong>Note:</strong> Since your browser does not support JavaScript, you must press the Resume button once to proceed.
            </p>
        </noscript>
        <form method="post" action="another_url.saml2">
                        <input type="hidden" name="SAMLRequest" value="really_long_token"/>
                        <input type="hidden" name="RelayState" value="token"/>
                        <noscript><input type="submit" value="Resume"/></noscript>
        </form>
    </body>
</html>

So I tried explicitly enabling JavaScript with:

options = webdriver.ChromeOptions()
options.add_argument("--enable-javascript")
driver = webdriver.Chrome(chrome_options=options)

This seems similar to Selenium test - Firefox alert disappearing immediately, but it looks like I can't recreate the solution using Chrome. I tried the following:

options = webdriver.ChromeOptions()
options.add_argument("--disable-popup-blocking")
driver = webdriver.Chrome(chrome_options=options)

But that made no difference either. Is there another way to prevent Selenium/Chrome from automatically closing the alert?

Here is a screenshot of the popup:

enter image description here

I have tried adding the following to the end of my script:

current_url = driver.current_url
parts = current_url.split('//')
login_url = parts[0] + '//{}:{}@'.format(username, password) + parts[1]
driver.get(login_url)

But this doesn't help. The login URL looks like this:

https://username:password@some_site/1S14/idp/G6tue/resume/idp/prp.ping?pfidpadapterid=idp.CG2LlmzHFUrah4EmDQ7jO_XTLGP&rememberChoice=true

liamvharris
  • 350
  • 3
  • 16
  • what happens if you remove the code that handles the alert box? e.g. delete `alert_obj = driver.switch_to.alert`. does the login happen successfully? or you get error for unexpected alert? – Jeni Oct 15 '19 at 16:14
  • Usually entering username and password does not happen in Alerts. Why do you expect an alert? Could it be possible this is another html element, and not alert box? – Jeni Oct 15 '19 at 16:22
  • post the markup for the login form... (if there is any...) If there is no markup, it could be a notification or an alert... It's worth mentioning that the default behavior for an unhandled prompt is to dismiss and notify... which means an exception would be thrown, so try/catch the last step to see if this happens. Also see this post: https://stackoverflow.com/questions/57481723/is-there-a-change-in-the-handling-of-unhandled-alert-in-chromedriver-and-chrome – pcalkins Oct 15 '19 at 22:11
  • Without the switch to alert, the script ends successfully, no errors to catch. I assumed it was an alert, but that's likely my inexperience, it could be something else. I'll post a screenshot of the popup. With it active I'm unable to inspect the site with Chrome (right-click does nothing) - is there another way to check if it has markup? – liamvharris Oct 16 '19 at 08:08
  • Open the inspector... F12 in Chrome. – pcalkins Oct 18 '19 at 23:30

2 Answers2

1

If the prompt you get is browser login, then you can try setting the username and password like this:

driver.get("https://username:password@somewebsite.com/")

as described in this post Selenium Python Authenticating browser login pupup dialog at a HTTPS website

But this IS NOT an ALERT, and that's why you can't handle it with driver.switch_to.alert, and you get the exception.

Jeni
  • 1,088
  • 12
  • 30
  • OK, I've tried this a few different ways with little success. Apologies I just realised I didn't mention in my question - this is a corporate intranet site. If I log in manually I have to give a domain with my username like `DOMAIN\username`. Following your suggestion with the domain in the username, I get blocked by my company's firewall, without the domain it makes no difference to the behaviour described in my question. I should note that my initial URL isn't the one with the login prompt, I navigate to that - is it possible to extract the current URL from a webdriver to start a new GET? – liamvharris Oct 16 '19 at 08:20
  • I've tried extracting the URL of the page with the login prompt, then using `driver.get('https://username:password@login_url')`, but that does the same thing as described in my last comment. I'll post the URL in my question. Also worth pointing out that if I login manually, I have to enter my credentials twice (I don't know why). – liamvharris Oct 16 '19 at 08:35
1

I have done a similar project for my firm, what you will have to do is browse to that URL using UI Automation (Lib:pyautogui) then input the username and password. After that you are free to do anything using Selenium.

Your code wont go beyond "driver.get(url)", it will be forever stuck there.