SELENIUM Can't access payment form/fields

Question:

https://squidindustries.co/checkout

    checkout_cc_number = driver.find_element_by_id("number")
    checkout_cc_number.send_keys(card_number)

When I try to input information into the card number field I get an error saying the element could not be located. I tried using time.sleep and driver.implicitly_wait when i first got to the page but both failed. Any ideas?

Asked By: jlc

||

Answers:

have you tried getting the input element using the DOM? what happens if you do document.getElementById('number') ?

Answered By: Savvii

The element is in a frame (i.e. a webpage within a webpage). Selenium will look for elements in the page it has loaded and not within frames. That’s the problem.

To solve this we just need a bit more code, which will tell Selenium to look in the frame.

The example you’ve given is several pages deep into a shopping cart, so I’m going to use a much more accessible example instead: the mozilla guide to iframes.

Here is some code to open that page and then click the CSS button within the frame:

from selenium import webdriver
import time

browser = webdriver.Chrome()
browser.get(r"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe")
time.sleep(5)

browser.switch_to.frame(browser.find_element_by_class_name("interactive"))
css_button = browser.find_element_by_id("css")
css_button.click()
browser.switch_to.default_content()

There are two lines that are important. The first one is:

browser.switch_to.frame(browser.find_element_by_class_name("interactive"))

That finds the frame and then switches to it. Once we have done that, any code that looks for elements will be looking in the frame and not in the page that we navigated to. That is what you need to do to access the number element. In your example the class of the frame is card-fields-iframe, so use that instead of interactive.

The second important line is:

browser.switch_to.default_content()

That reverts the previous line. So now Selenium will be looking for elements within the page that we navigated to. You’ll want to do that after interacting with the frame, so that you can continue through the shopping cart.

Answered By: Robson

I ran into the same issue, and with checkouts, as you mentioned, all the iframe class names are the same. What I did was get all the iframes with the same class name as a list:

iframes = driver.find_elements(By.CLASS_NAME, "card-fields-iframe")

I then switched through the iframes referencing each one by its place in the list. Since there are only four fields in the checkout, the list is only 4 elements long, starting with [0].

    driver.switch_to.frame(iframes[0])
    number = driver.find_element(By.ID, "number")
    if number.is_displayed:
        number.send_keys("4000300040005000") 
    driver.switch_to.default_content()

It’s important to note that switching back to the default content, using driver.switch_to.default_content(), before switching to the next frame is the only way I was able to make this work. The is_displayed function just checks to see whether the element is on the page or not.

Answered By: Fincent Enterprises