The current Stripe configuration puts cardnumber, the expiry date (exp-date) and cvc in different iframes. Unlike before, all are in one iframe and the solution above worked.
I was able to update the card information by just transferring to one iframe. Then the Stripe changes came and the front-end developer updated the payment web page. Then came the 'Unable to locate element ...' error for the expiry date and the cvc. Likewise, I asked the developer if he can put id's or names for the 3 inputs. He said, he cannot do it and Stripe makes the payment screen.
Normally, when you inspect in Firefox or in Chrome the credit card infos, you will see what iframe the inputs belong to.
In our web page, the cardnumber is in the __privateStripeFrame5. The exp-date is in the __privateStripeFrame6, and the cvc in the __privateStripeFrame7.
Here's the code that solved my dilemma in updating/testing the card infos using selenium python (java has similar methods/functions):
# has_zip_code - True or False
# added params for flexibility
# exp_date - expiration date
# cvc_val - 3-digit number
def enter_card_details_and_submit(driver, card_num, exp_date, cvc_val, has_zip_code):
#print("\n{} -------------------------------------------\n".format(PI_WIN))
print("Use card number ... {}".format(card_num))
print(card_num)
driver.switch_to.frame(frame_reference=wait_and_get_elem_by(driver, By.NAME, "__privateStripeFrame5"))
card_num_text = wait_and_get_elem_by(driver, By.NAME, "cardnumber")
card_num_text.click()
time.sleep(1)
card_num_text.send_keys(card_num)
driver.switch_to.default_content()
print("\nEnter expiry month/year ...")
iframe6 = wait_and_get_elem_by(driver, By.NAME, "__privateStripeFrame6")
driver.switch_to.frame(iframe6)
exp_dt = wait_and_get_elem_by(driver, By.NAME, "exp-date")
exp_dt.click()
time.sleep(1)
exp_dt.send_keys(exp_date)
driver.switch_to.default_content()
print("\nEnter CVC ...")
driver.switch_to.frame(frame_reference=wait_and_get_elem_by(driver, By.NAME, "__privateStripeFrame7"))
cvc = wait_and_get_elem_by(driver, By.NAME, "cvc")
cvc.click()
time.sleep(1)
cvc.send_keys(cvc_val)
.
.
.
wait_and_get_elem_by() is an internal function that finds the element but with wait() function in it. You can use find_element_by_name().
The cardnumber, exp-date, and cvc are updated using selenium (python):
switch_to.default_content()
and no need totime.sleep(1)
. I find the Stripe iframe with the following css selector:"div.__PrivateStripeElement iframe"
– Twelvemo