Selecting incorrect submenu item after hover action - python

I'm developing a test case in Python with Webdriver to click through menu items on http://www.ym.com, and this particular one is meant to go through a menu item and click on a sub-menu item.
When running the test, it looks like it tries to access the nested menu items, but never clicks on the final item. Here is my code to go through the menu:
food = driver.find_element_by_id("menu-item-1654")
hov = ActionChains(driver).move_to_element(food).move_to_element(driver.find_element_by_xpath("/html/body/div[4]/div/div/ul/li[2]/ul/li/a")).click()
hov.perform()
The problem here is that I am trying to click the "Recipes" submenu from the "Food" menu, but what happens is the submenu "France" is being clicked under the menu "Travel" which is situated right next to "Recipes.
I've tried using find_element_by_id, find_element_by_css_locator, find_element_by_link_text but it seems to always select the France submenu under Travel and not the Recipes submenu under Food.
Any ideas?
EDIT
I am using this Python code to run the test now:
food = driver.find_element_by_xpath("//a[contains(#href, 'category/food/')]/..")
ActionChains(driver).move_to_element(food).perform()
WebDriverWait(driver, 5).until(lambda driver: driver.find_element_by_xpath("//a[contains(#href, 'category/recipes-2/')]/..")).click()
which works perfectly fine in IE, but still access the wrong menu item in Firefox.

Try use normal click instead of ActionChains' move and click.
Changes to your code:
I assume the ids are dynamic, try avoid using them.
Try avoid using absolute xpath
Use normal click rather than ActionChain move and click
Use 5 seconds WebDriverWait for recipes link.
food = driver.find_element_by_xpath("//a[contains(#href, 'category/food/')]/..")
hov = ActionChains(driver).move_to_element(food).move_by_offset(5, 45).perform()
# 45 is the Height of the 'FOOD' link plus 5
recipes = WebDriverWait(driver, 5).until(lambda driver: driver.find_element_by_xpath("//a[contains(#href, 'category/recipes-2/')]/.."))
recipes.click()
A tested working C# version of the code:
driver.Navigate().GoToUrl("http://www.yumandyummer.com");
IWebElement food = driver.FindElement(By.XPath("//a[contains(#href, 'category/food/')]/.."));
new Actions(driver).MoveToElement(food).MoveByOffset(5, food.Size.Height + 5).Perform();
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
IWebElement recipes = wait.Until(ExpectedConditions.ElementExists(By.XPath("//a[contains(#href, 'category/recipes-2/')]/..")));
recipes.Click();

Maybe your XPath is off? Could you try this for the XPath instead:
find_element_by_xpath("//ul[#id='menu-more-menu-items']//li[2]//ul/li[1]/a[1]")

Possibly not that helpful, but in java I have used
new Select(driver.findElement(By.id("MyId"))).selectByVisibleText("MyText");

Related

How to hover over and expand dropdown menu on komoot with selenium?

My goal is to get an element within a dropdown menu that needs to be clicked in order to appear using python selenium. Also, it seems that before the click, hovering is necessary.
I tried to click the dropdown menu like this:
element = wait().until(EC.presence_of_element_located((By.CLASS_NAME, "c-topmenu c-topmenu--create c-topmenu--userbar tw-inline-flex")))
element.click()
def wait():
return WebDriverWait(driver, 30)
And tried to use hovering:
Hover = ActionChains(driver).move_to_element(element)
Hover.click().build().perform()
Still, I get a TimeoutException and can't figure out a solution.
The website komoot looks like this before clicking the dropdown menu:
The website komoot looks like this after expanding it:
Ok here is how i was able to get this working.
after the login i grapped the wrapper element from the link with:
more_menu_wrapper = driver.find_element_by_css_selector("div[data-test-id='more_menu']")
after that i could click the desired element with:
more_menu_wrapper.find_element_by_tag_name("a").click()
You are using a wrong locator.
In case of multiple class names you should use css_selector or XPath, not by class name.
Also, here you have an unique attribute of data-test-id, you should use it.
Also, you should wait for element visibility or clickability, not just for element presence.
So your code could be:
element = wait().until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div[data-test-id='more_menu']")))

How click in Button with Selenium python

I want to click the configuration button, which leads to discord profile information,
Guys, I want to click on the gear at the bottom, how can I do this? This is my code:
option = Options()
option.add_argument("--no-sandbox")
driver = webdriver.Chrome(options=option)
driver.get("https://discord.com/channels/395582581124497408/395582581124497412")
wait = WebDriverWait(driver, 5)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'a.item'))).click()
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div#contents-18-Yxp"))).click()
Can anyone help me with this problem?
you can click it with this code:
driver.find_element_by_css_selector('div'[aria-label="User settings"]').click()
Find the ID of that button, then use driver.find_element_by_id("ID").click()
You should read this tutorial https://www.geeksforgeeks.org/click-element-method-selenium-python/
First, you must get an identifier for your element, for example:
class
xpath
css selector
... etc
then drive.find_element_by_(class, xpath, ...)(string).click()
Example:
driver.find_element_by_xpath('(//*[#class="contents-18-Yxp"])[7]')
this is the identifier for the settings section, you can copy it, note that this xpath can be changed if the discoed is updated, the solution is easy, just with the same way get the new xpath and paste it instead of the old one.
with the same Technique, find the user profile identifier, and paste it and remember .click()

What is wrong with my xpath? Why is a different element receiving the click?

Steps to recreate:
Go to http://practice.automationtesting.in/
Click on add to basket
Then view basket
Change the quantity to 2
Click on Update Basket
Click on remove item'X'
Or use coupon code "krishnasakinala"
Click on Apply Coupon button
The error I am getting is:
selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element ... is not clickable at point (216, 220). Other element would receive the click:
I have tried different locators but getting the same error.
Read more: https://softwaretestingboard.com/q2a/4041/exceptions-elementclickinterceptedexception-intercepted#ixzz6iUxRC97y
My code:
url = "http://practice.automationtesting.in"
driver.get(url)
wait_timeout = 5
wait_variable = W(driver, wait_timeout)
driver.find_element_by_xpath("//a[#data-product_id='160']").click()
wait_variable.until(E.presence_of_element_located((By.XPATH, "//a[#class ='added_to_cart wc-forward']"))).click()
wait_variable.until(E.presence_of_element_located((By.XPATH, "//input[#type='number']"))).clear()
wait_variable.until(E.presence_of_element_located((By.XPATH, "//input[#type='number']"))).send_keys(2)
wait_variable.until(E.element_to_be_clickable((By.NAME, "update_cart"))).click()
wait_variable.until(E.presence_of_element_located((By.XPATH, "//a[#title='Remove this item']"))).click()
There are multiple ways to solve this problem like making the driver wait, using a different element identifier (CSS/class/etc.) but the most effective one is to use the method execute_script()
element = driver.find_element_by_xpath('the xpath of the element')
driver.execute_script("arguments[0].click();", element)
wait_variable.until(E.element_to_be_clickable(
(By.NAME, "update_cart"))).click()
wait_variable.until(E.presence_of_element_located(
(By.CSS_SELECTOR,'[class="blockUI blockOverlay"]')))
wait_variable.until(E.staleness_of(
driver.find_element_by_css_selector('[class="blockUI blockOverlay"]')))
wait_variable.until(E.presence_of_element_located(
(By.XPATH, "//a[#title='Remove this item']"))).click()
The error is due to the overlay loader use this code , using javascript to click an element is not a right way it will bypass the UI rendering and direcly trigger click event on the element.
This should be avoided if you are using selenium for testing
How to find locator for overlay loader:
what is overlay loader :
This spinner is a UI element used to block user interaction with UI while ajax components are being loaded in the background.
What are the challenges:?
The spinner load so fast that it is hard to locate the element from dev tool
How to find the locator?
open element tab , right click the html and seelct break on sub tree modification
now click play button:
click update cart and click the blue play button till the loader is present in the UI.
This will freeze UI with the spiner in screen , now you can easily find the locator

Loop until button is available Python Selenium

I'm coding my first "bot" with python and webdriver
I would like to loop until a specific button shows up on the website. My idea is to check if the button is available. If not, sleep for a minute, reload, and check again. But I dont know the right syntax as this element seems too complicated for me.
Does anyone have a tip?
Edit: When the product is sold out, this button does not exist on the product page. I guess enabled/disabled won't work here, because the button does not exist if the product is unavailable. I guess I need to check, if the button exists.
You can use WebDriverWait in python selenium to wait till the element is loaded. Or you can use javascript to check if the element exists in the DOM or not:
buttons = document.getElementsByClassName("mu-button mu-button--type_alternative add-to-cart");
if (buttons.length == 0) {
# it doesn't exist
} else
{
# do something
}
Full documentation: https://selenium-python.readthedocs.io/waits.html
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)

Selenium - Click at certain position

Using the Python version of Selenium, is it possible to click some element in the DOM and to specify the coordinates where you want to click it?
The Java version has the method clickAt, which actually does exactly what I am looking for, but can't find the equivalent in Python.
This should do it! Namely you need to use action chains from webdriver. Once you have an instance of that, you simply register a bunch of actions and then call perform() to perform them.
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.google.com")
el=driver.find_elements_by_xpath("//button[contains(string(), 'Lucky')]")[0]
action = webdriver.common.action_chains.ActionChains(driver)
action.move_to_element_with_offset(el, 5, 5)
action.click()
action.perform()
This will move the mouse 5 pixels down and 5 pixels right from the upper-left corner of the button I feel lucky. Then it will click().
Notice that you must use perform(). Else nothing will happen.
The reason you are getting confused is clickAt is an old v1 (Selenium RC) method.
WebDriver has a slightly different concept, of 'Actions'.
Specifically, the 'Actions' builder for the Python bindings live here.
The idea of the clickAt command is to click at a certain position relative to a particular element.
The same is achievable within the WebDriver, using the 'Actions' builder.
Hopefully this updated documentation can help.
You can perform the task with the Action chains in the python specially with Edge browser:
from selenium.webdriver import ActionChains
actionChains = ActionChains(driver)
button_xpath = '//xapth...'
button = driver.find_element_by_xpath(button_xpath)
actionChains.move_to_element(button).click().perform()
But sometimes Action chain does not finds the DOM element. Hence better option to use execute scipt in following way:
button_xpath = '//xapth...'
button = driver.find_element_by_xpath(button_xpath)
driver.execute_script("arguments[0].click();", button)
I've not personally used this method, but looking through the source code of selenium.py I've found the following methods that look like they'd do what you want - They look to wrap clickAt:
def click_at(self,locator,coordString):
"""
Clicks on a link, button, checkbox or radio button. If the click action
causes a new page to load (like a link usually does), call
waitForPageToLoad.
'locator' is an element locator
'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator.
"""
self.do_command("clickAt", [locator,coordString,])
def double_click_at(self,locator,coordString):
"""
Doubleclicks on a link, button, checkbox or radio button. If the action
causes a new page to load (like a link usually does), call
waitForPageToLoad.
'locator' is an element locator
'coordString' is specifies the x,y position (i.e. - 10,20) of the mouse event relative to the element returned by the locator.
"""
self.do_command("doubleClickAt", [locator,coordString,])
They appear in the selenium object and here is their online API documentation.

Categories

Resources