Working with Python and Selenium Chrome Driver - python-3.x

I was hoping for maybe some clarification or suggestions on how to get selenium working with a href I have tried selecting it by pretty much every element possible.
My end goal would be to loop through each "Case Number" and click on it and once finished add each one to a list, then if it is not in the list click on it until finished.
<td class="x-grid3-col x-grid3-cell x-grid3-td-CASES_CASE_NUMBER " style="width:172px;" tabindex="0"><div class="x-grid3-cell-inner x-grid3-col-CASES_CASE_NUMBER" id="5005a00001rezYE_CASES_CASE_NUMBER">0000000</div></td>
<div class="x-grid3-cell-inner x-grid3-col-CASES_CASE_NUMBER" id="5005a00001rezYE_CASES_CASE_NUMBER">0000000</div>
0000000
clicky = driver.find_element_by_css_selector("//div[#id='5005a00001rezYE_CASES_CASE_NUMBER']").click()
I have also tried with this element(which would make it easier for what I am trying to do)
<span>Edit</span>
<span>Edit</span>
clicky = driver.find_element_by_xpath("span[contains(text(),'Edit')]").click()
clicky = driver.find_element_by_css_selector("span[Edit]").click()

I'm not sure this locator is correct and unique, but you can try this:
clicky = driver.find_element_by_xpath("//span[contains(text(),'Edit')]").click()
Possibly you will have to add some delay / wait before accessing this element.
The simplest way is to add a delay
time.sleep(5)
clicky = driver.find_element_by_xpath("//span[contains(text(),'Edit')]").click()
While recommended approach is to add an explicit wait, like this:
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.XPATH, "//span[contains(text(),'Edit')]"))).click()
For this you will need to add these imports:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

Related

Buttons click with selenium webdriver not work/not found

Actually, i have a script with python 3.10, selenium, undetected-chromedriver and i want to click on two buttons on this webpage:
https://keepa.com/#!
Buttons are french flag, and ".fr" here:
And html code for these two buttons are here:
-first highlighted is flag fr
-second is country ".fr"
I've tested somes part of script, but not work actually:
For language flag fr:
driver.find_element(By.XPATH, "(//span[#id='lang_fr'])").click()
driver.find_element(By.ID,"lang_fr").click()
For country .fr:
driver.find_element(By.XPATH, "(//span[#setting='4'])").click()
driver.find_element(By.XPATH, "(.//span[contains(text(), '.fr')])").click()
I have somes errors on results, "element not found", or this:
selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable
Anyone can help me or have an idea where is the problem please?
Thanks for help, bye!
You have to click on default flag first and then there will be 2 button which you can click like below:
Code:
driver_path = r'C:\\Users\\****\\***\\Desktop\\Automation\\chromedriver.exe'
driver = webdriver.Chrome(driver_path)
driver.maximize_window()
driver.get("https://keepa.com/#!")
wait = WebDriverWait(driver, 30)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div#currentLanguage .languageMenuText"))).click()
flag = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "img#lang_fr")))
flag.click()
lang = wait.until(EC.visibility_of_element_located((By.XPATH, "//span[text()='.fr']")))
lang.click()
Imports:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
You can try the below code it will help you (this is using java though, ).
Actions actions = new Actions(driver);
WebElement ctr;
ctr= driver.findElement(By.xpath("//*[contains(text(),'YOUR DESIRED TEXT')]"));
Thread.sleep(1000);
actions.click(spatial).perform();

Selenium TimeoutException Error on clicking a button despite using EC.visibility_of_element_located().click() method?

I am trying to create an Account on Walmart using selenium python. I successfully opened https://www.walmart.com/ and successfully go to create an account button under Sign In tab. Moreover, I also successfully entered the details of First name, Last name, Email Address and Password. However, once I clicked on Create account button, I got TimeoutException error despite using EC.visibility_of_element_located().click () method.
Can anyone kindly guide me what is wrong with my approach. Thanks in advance.
The source code of the website for Create Account button is as follows:
<button class="button m-margin-top text-inherit" type="submit" data-automation-id="signup-submit-btn" data-tl-id="signup-submit-btn" aria-label="Create Account, By clicking Create Account, the user is acknowledging that they have read and agreed to the Terms of Use and Privacy Policy">Create account</button>
My Python code is as follows:
import time
import requests
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.action_chains import ActionChains
url = "https://www.walmart.com/"
first_name = "chuza"
last_name = "123"
email_id = "chuza123#gmail.com"
password = "Eureka1#"
options = Options()
s=Service('C:/Users/Samiullah/.wdm/drivers/chromedriver/win32/96.0.4664.45/chromedriver.exe')
driver = webdriver.Chrome(service=s, options=options)
driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source":
"const newProto = navigator.__proto__;"
"delete newProto.webdriver;"
"navigator.__proto__ = newProto;"
})
wait = WebDriverWait(driver, 20)
actions = ActionChains(driver)
driver.get(url)
sign_in_btn = wait.until(EC.visibility_of_element_located((By.XPATH, "//div[text()='Sign In']")))
actions.move_to_element(sign_in_btn).perform()
time.sleep(0.5)
wait.until(EC.visibility_of_element_located((By.XPATH, '//button[normalize-space()="Create an account"]'))).click()
f_name = driver.find_element(By.ID, 'first-name-su')
l_name = driver.find_element(By.ID, 'last-name-su')
email = driver.find_element(By.ID, 'email-su')
pswd = driver.find_element(By.ID, 'password-su')
f_name.send_keys(first_name)
driver.implicitly_wait(2)
l_name.send_keys(last_name)
driver.implicitly_wait(1.5)
email.send_keys(email_id)
driver.implicitly_wait(2)
pswd.send_keys(password)
driver.implicitly_wait(0.5)
###
wait.until(EC.visibility_of_element_located((By.XPATH, '//button[normalize-space()="Create account"]'))).click()
I see this css selector that represent the desired webelement:
button[data-automation-id='signup-submit-btn']
and xpath would be:
//button[#data-automation-id='signup-submit-btn']
there are 3 matching nodes for each CSS and XPath and Selenium will look for the first match, the CSS and XPath basically are first matching node.
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-automation-id='signup-submit-btn']"))).click()
or
wait.until(EC.element_to_be_clickable((By.XPATH, "//button[#data-automation-id='signup-submit-btn']"))).click()
It makes more sense to use element_to_be_clickable when trying to click on a web element instead of visibility_of_element_located. Also, CSS are much better locator as compared to XPath.
//button[normalize-space()="Create account"] locator matches 3 elements on that page, you need to use more precise locator.
This locator is unique: //form[#id='sign-up-form']//button[#data-tl-id='signup-submit-btn']
So, this should work:
wait.until(EC.visibility_of_element_located((By.XPATH, "//form[#id='sign-up-form']//button[#data-tl-id='signup-submit-btn']"))).click()
This xpath based Locator Strategy...
//button[normalize-space()="Create account"]
...identifies three(3) elements within the DOM Tree and your desired element is the second in the list.
Solution
The desired element is a dynamic element so to click on the clickable element instead of visibility_of_element_located() you need to induce WebDriverWait for the element_to_be_clickable() and you can use the following Locator Strategy:
Using XPATH:
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//form[#id='sign-up-form']//button[normalize-space()='Create account']"))).click()
Note: You have to add the following imports :
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
This issue is because of selenium, you can fix this by creating it manually, follow the steps:
Create an account on Walmart IO platform here by clicking on the man icon just before the search box.
Login to the account and accept "Terms of Use"
Click on "Create Your Application" to create a new application and fill in appropriate details.
You can follow this tutorial to generate two sets of public/private keys -one set will be used for production and the other set will be used for stage.
Upload both public keys using this: https://walmart.io/key-upload?app_name=<your app name>
Consumer ID will be generated for both sets for prod and stage which can be seen on the dashboard
Click on "Request Access" for OPD APIs at here and fill out the form

Selenium- Click a button issue

using imports:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.ui import WebDriverWait
using this def to navigate to the exact iFrame that the button is under :
def changeIframetoManagement():
wait2 = WebDriverWait(driver, 10)
wait2.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "moduleManagement")))
my attempt to achieve that task :
changeIframetoManagement()
driver.find_element_by_css_selector("body > div.bootbox.modal.fade.show-order-info-bootbox-
container.in > div > div > div.modal-body > button").click()
im also tried to reach by xPath like this
driver.find_element_by_xpath("//html/body/div[5]/div/div/div[1]/button").click()
that is the last i frame i was in
def changeIframetoOrders():
wait3 = WebDriverWait(driver, 10)
wait3.until(EC.frame_to_be_available_and_switch_to_it((By.NAME,
"orderInfo")))
After switching into the iframe try this:
driver.find_element_by_css_selector("div.modal-dialog button.bootbox-close-button").click()
UPD
According to your last comments, since you previously switched into iframe located by orderInfo name, before switching into iframe located by moduleManagement id you have yo switch to the default content, like this:
changeIframetoOrders()
driver.switch_to.default_content()
changeIframetoManagement()
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.modal-dialog button.bootbox-close-button"))).click()
See if this xpath works:-
driver.find_element_by_xpath(".//button[contains(#class,'close-button')]").click()
The x button is in moduleManagement iframe.
and the goal is to click on it using Selenium.
as per OP
wait3.until(EC.frame_to_be_available_and_switch_to_it((By.NAME,
"orderInfo")))
looks like he was in a different iframe orderInfo.
So I would suggest whenever you are done with any iframe stuff, always switch the control back to default content like below :
driver.switch_to.default_content()
Now again you will have to switch to moduleManagement iframe like below :
wait = WebDriverWait(driver, 10)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "moduleManagement")))
and click on x button like this :
wait.until(EC.element_to_be_clickable((By.XPATH, "//button[contains(#class, ''bootbox-close-button) and text()='x']"))).click()

How do I wait until text of element changes to something else than a string?

I'm using selenium with Python 3 to retrieve the contents from an element on a webpage. There is an element with dynamic text.
<div id="accResp">Please wait...</div>
The "Please wait..." section changes to different strings like "Password Incorrect", "Loading".
How do I wait until the string changes to anything except "Please wait..."?
Based on your functionality you will see text in your web page so you can handle text using below xpath's:
wait = WebDriverWait(driver, 10)
password Incorrect
passwordIncorrect = wait.until(EC.element_to_be_clickable((By.XPATH, "//div[contains(text(),'Password Incorrect')]")))
Loading
loading = wait.until(EC.element_to_be_clickable((By.XPATH, "//div[contains(text(),'Loading')]")))
Please wait...
waitText= wait.until(EC.element_to_be_clickable((By.XPATH, "//div[contains(text(),'Please wait...')]")))
Note : please add below imports to your solution
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

How do i use “wait until” element before certain page is displayed? (using python 3.7)

First of all, i am a newbie in testing app using appium (python 3.7). Here, i am testing an app where i have to wait right after login process is completed. I have done this using implicit wait. But now, to make the testing process more dynamic i want to wait until the next page is displayed.
Note: I have seen and tried several issues of this forum but could not help myself.
Here's the code:
from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
desired_cap = {
"platformName": "Android",
"deviceName": "QDG9X18426W11577",
"newCommandTimeout": "240",
"app": "C:\\Users\\tahmina\\Downloads\\test-v3.10.apk",
"appPackage": "com.cloudapper.android",
"appActivity": "com.cloudapper.android.SplashActivity"
}
#Making connection with Appium server
driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_cap)
#Here i have used implicit wait to load the login page
driver.implicitly_wait(20)
#Login to the app
search_element = driver.find_element_by_id('Username').send_keys('test#yandex.com')
search_element = driver.find_element_by_id('Password').send_keys('1155qQQ')
search_element = driver.find_element_by_xpath(
'/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout[2]/android.webkit.WebView/android.webkit.WebView/android.view.View/android.view.View[2]/android.widget.Button').click()
wait = WebDriverWait(driver, 10)
#Waiting until the next process comes up
if webdriver.wait.until(driver.find_element_by_id('com.cloudapper.android:id/item_bg').is_displayed()):
print('Run the next process')
elif webdriver.wait.until(not driver.find_element_by_id('com.cloudapper.android:id/item_bg')):
print('Something went wrong!')
#Searching employee by using ID
search_element = driver.find_element_by_id('com.cloudapper.android:id/edtSearch').send_keys('1018')
driver.execute_script('mobile:performEditorAction', {'action': 'search'})
Guide me if anyone of you have any solution about it.
With Python, you can use WebDriverWait and ExpectedConditions to solve your problem.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
#Login to the app
search_element = driver.find_element_by_id('Username').send_keys('test#yandex.com')
search_element = driver.find_element_by_id('Password').send_keys('1155qQQ')
search_element = driver.find_element_by_xpath(
'/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout[2]/android.webkit.WebView/android.webkit.WebView/android.view.View/android.view.View[2]/android.widget.Button').click()
# Waiting until the next process comes up
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "com.cloudapper.android:id/item_bg")))
If you want to implement the WebDriverWait in a try / except block, you can handle the case where your desired element does not appear on the page:
from selenium.common.exceptions import TimeoutException
# Waiting until the next process comes up
try:
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "com.cloudapper.android:id/item_bg")))
except TimeoutException as ex:
# handle the exception here
print("Exception has been thrown. " + str(ex))
Because you are using the explicit wait.until keyword, you should not set driver Implicit wait. It is bad practice to set both implicit and explicit wait in your automation tests, and can yield unexpected wait times.
On another note -- I noticed you are using explicit XPath notation in some of your selectors. XPath is a great method for selecting elements, but using explicit selectors as such makes your code very brittle. I recommend using relative selectors instead. You can replace this:
search_element = driver.find_element_by_xpath(
'/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout[2]/android.webkit.WebView/android.webkit.WebView/android.view.View/android.view.View[2]/android.widget.Button').click()
with this:
search_element = driver.find_element_by_xpath('//android.widget.Button').click()
You may have to query on additional attributes such as text --
search_element = driver.find_element_by_xpath('//android.widget.Button[#text='Log in']').click()
Overall, this method is much more efficient.
Have you tried something like this:
import time
time.sleep(0.5)
This is for anyone who face the same problem:
Import WebDriverWait and ExpectedConditions
Use this as explicit wait in your code
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "com.cloudapper.android:id/item_bg")))

Resources