AttributeError: 'WebDriver' object has no attribute 'find_element_by_id' - Selenium Webdriver [duplicate] - selenium

When starting the function
def run(driver_path):
driver = webdriver.Chrome(executable_path=driver_path)
driver.get('https://tproger.ru/quiz/real-programmer/')
button = driver.find_element_by_class_name("quiz_button")
button.click()
run(driver_path)
I'm getting errors like these:
<ipython-input-27-c5a7960e105f>:6: DeprecationWarning: executable_path has been deprecated, please pass in a Service object
driver = webdriver.Chrome(executable_path=driver_path)
<ipython-input-27-c5a7960e105f>:10: DeprecationWarning: find_element_by_* commands are deprecated. Please use find_element() instead
button = driver.find_element_by_class_name("quiz_button")
... but I can't understand why.
I'm using WebDriver at the latest version for my Chrome's version. I don't why I get
find_element_by_* commands are deprecated
... when it's in the documentation that the command exists.

This error message...
DeprecationWarning: find_element_by_* commands are deprecated. Please use find_element() instead
...implies that the find_element_by_* commands are deprecated in the latest Selenium Python libraries.
As AutomatedTester mentions: This DeprecationWarning was the reflection of the changes made with respect to the decision to simplify the APIs across the languages and this does that.
Solution
Instead you have to use find_element(). As an example:
You have to include the following imports
from selenium.webdriver.common.by import By
Using class_name:
button = driver.find_element_by_class_name("quiz_button")
Needs be replaced with:
button = driver.find_element(By.CLASS_NAME, "quiz_button")
Along the lines of, you also have to change the following:
Using id:
element = find_element_by_id("element_id")
Needs be replaced with:
element = driver.find_element(By.ID, "element_id")
Using name:
element = find_element_by_name("element_name")
Needs be replaced with:
element = driver.find_element(By.NAME, "element_name")
Using link_text:
element = find_element_by_link_text("element_link_text")
Needs be replaced with:
element = driver.find_element(By.LINK_TEXT, "element_link_text")
Using partial_link_text:
element = find_element_by_partial_link_text("element_partial_link_text")
Needs be replaced with:
element = driver.find_element(By.PARTIAL_LINK_TEXT, "element_partial_link_text")
Using tag_name:
element = find_element_by_tag_name("element_tag_name")
Needs be replaced with:
element = driver.find_element(By.TAG_NAME, "element_tag_name")
Using css_selector:
element = find_element_by_css_selector("element_css_selector")
Needs be replaced with:
element = driver.find_element(By.CSS_SELECTOR, "element_css_selector")
Using xpath:
element = find_element_by_xpath("element_xpath")
Needs be replaced with:
element = driver.find_element(By.XPATH, "element_xpath")
Note: If you are searching and replacing to implement the above changes, you will need to do the same thing for find_elements_*, i.e., the plural forms of find_element_*.
You may also find this upgrade guide useful as it covers some other unrelated changes you may need to make when upgrading: Upgrade to Selenium 4

#DebanjanB mentioned and explained the new structure. Also, it's better use these lines:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service
s = Service('C:/Users/.../chromedriver.exe')
driver = webdriver.Chrome(service=s)

As others mentioned, you should use find_element() or find_elements() instead of find_element_by_*() or find_elements_by_*().
I wrote the regex pattern to replace the deprecated methods to new ones, so try this if you need.
# from - e.g. find_element_by_id("test")
find_element(s?)_by_([a-z]+)\((.*)
# to - e.g. find_element(By.ID, "test")
find_element$1(By.\U$2\E, $3
Note: you need the import line to use the new methods
from selenium.webdriver.common.by import By

Thank you #Stephen and undetected Selenium for your answers. After some time reading on how where to find an example of send_key, I found an amazing gist of examples.
The send_keys below example worked for me:
browser = webdriver.Chrome()
 
def test_key_down(driver):
driver.get('https://www.selenium.dev/selenium/web/single_text_input.html?#')
ActionChains(driver) \
.send_keys("abc") \
.perform()
 
test_key_down(browser)

Related

Selenium element selection issues and VSCode bug? Automate the Boring Stuff chapter 12

I'm attempting to replicate this code:
from selenium import webdriver
browser = webdriver.Firefox()
browser.get('https://inventwithpython.com')
try:
elem = browser.find_element_by_class_name(' cover-thumb')
print('Found <%s> element with that class name!' % (elem.tag_name))
except:
print('Was not able to find an element with that name.')
But it keeps returning the exception. I'm running this on mac w. vscode and there are few things off.
find_element_by_class_name method doesn't seem to register as a method.
Everytime I run this Intellicode prompts get disabled
I can't run this at all on Chrome as it crashes the chrome browsers
I've also searched online for driver issues and have done webdriver with the chrome driver path. Didn't work either
This is the error I'm getting if run it without try and except.
elem = browser.find_element_by_class_name(' cover-thumb') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'WebDriver' object has no attribute 'find_element_by_class_name'
Selenium removed that method in version 4.3.0. See the CHANGES: https://github.com/SeleniumHQ/selenium/blob/a4995e2c096239b42c373f26498a6c9bb4f2b3e7/py/CHANGES
Selenium 4.3.0
* Deprecated find_element_by_* and find_elements_by_* are now removed (#10712)
* ...
You now need to use:
driver.find_element("class name", "VALUE_OF_CLASS_NAME")
Eg:
driver.find_element("class name", "cover-thumb")
But if a class name has multiple segments, use the dot notation from a CSS Selector:
driver.find_element("css selector", "img.cover-thumb")

javascript error: Right-hand side of 'instanceof' is not an object error using expected_conditions with Selenium Python

I have some code in selenium/python, which used to work, But now I'm getting:
javascript error: Right-hand side of 'instanceof' is not an object
I don't know if it's something that was changed in the angular application, or how this error is relevant to what I'm doing.
I get it after trying to locate a webelement or waiting for visibility of element, like:
wait.until(expected_conditions.visibility_of_element_located(leftNav_page.pageSmallTitle))
"pageSmallTitle" is just a locator like:
pageSmallTitle = (By.CSS_SELECTOR, "span[id$='componentTitle']")
Tried changing it to xpath, but didn't make a difference.
I would highly appreciate any suggestion!
visibility_of_element_located() accepts a locator as an argument and the expression is as follows:
wait.until(expected_conditions.visibility_of_element_located((By.CSS_SELECTOR, "span[id$='componentTitle']")))
In your usecase, if:
pageSmallTitle = (By.CSS_SELECTOR, "span[id$='componentTitle']")
the effective line of code must have been:
from selenium.webdriver.support import expected_conditions
wait.until(expected_conditions.visibility_of_element_located(pageSmallTitle))
so essentially there is an additional parameter as leftNav_page. Hence you see the error.
Removing the extra parameter will solve the issue.

Python move_to_element().click() is not pressing a right element visible on the screen or returns the error. A trial code is included

I try to interact with the elements (button at this scenario) inside Disqus iframe on this webpage:
This is my trial code:
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import time
path_to_chromedriver = r"c:\users\tv21\source\repos\chromedriver.exe"
driver = webdriver.Chrome(executable_path=path_to_chromedriver)
driver.maximize_window()
url = "https://www.postoj.sk/91472/po-navsteve-kina-si-precitajte-aj-kniznu-predlohu"
driver.get(url)
time.sleep(5)
button_to_close = driver.execute_script("return document.querySelector('body').querySelector('div.grv-dialog-host').shadowRoot.querySelector('div').querySelector('div.buttons-wrapper').querySelector('button.sub-dialog-btn.block_btn')")
ac = ActionChains(driver)
ac.move_to_element(button_to_close).click().perform()
open_discussion = driver.find_element_by_class_name('article-disqus-wrapper')
driver.execute_script("arguments[0].setAttribute('style','display: block;')", open_discussion)
disqus_thread = driver.find_element_by_id("disqus_thread")
iframe_element = disqus_thread.find_element_by_tag_name("iframe")
driver.switch_to.frame(iframe_element)
time.sleep(1)
button_to_load_more = driver.find_element_by_partial_link_text("Nahraj viac komentárov")
ac = ActionChains(driver)
ac.move_to_element(button_to_load_more).click().perform()
The issue is the last command:
ac.move_to_element(button_to_load_more).click().perform()
which shows an error: "move target out of bounds"
I tried instead:
button_to_load_more.click()
and
driver.execute_script("arguments[0].click();", button_to_load_more)
which both work completely fine as the alternatives and I can click the button.
However, I try to understand the reason for being out of bounds when using move_to_element(). I get exactly the same error always when I want to hover over any elements inside Disqus iframe too.
Can anyone help me to fix it or explain to me how to fix it?
First one dint worked because of the known issue in selenium,i guess you are using 3.4 hence facing this.(But it should work after trying newer version of selenium)
Some of the useful links fyr
Selenium MoveTargetOutOfBoundsException even after scrolling to element
https://github.com/SeleniumHQ/selenium/issues/4148

Trying to find the correct xpath

I have made code, see following lines:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
from selenium.webdriver.common.by import By
PATH = "C:\Program Files (x86)\chromedriver.exe"
driver = webdriver.Chrome(PATH)
driver.get("https://www.flashscore.com/match/jBvNMej6/#match-summary")
print(driver.title)
driver.maximize_window() # For maximizing window
driver.implicitly_wait(10) # gives an implicit wait for 20 seconds
driver.find_element_by_id('onetrust-reject-all-handler').click()
time.sleep(2)
driver.find_element(By.CLASS_NAME,'previewShowMore.showMore').click()
main = driver.find_element(By.CLASS_NAME,'previewLine'[b[text()="Hot stat:"]]/text)
print(main.text)
time.sleep(2)
driver.close()
However, I get the following error.
main = driver.find_element(By.CLASS_NAME,'previewLine'[b[text()="Hot stat:"]]/text)
^
SyntaxError: invalid syntax
What can I do to avoid this?
thx! : )
Well, in this line
main = driver.find_element(By.CLASS_NAME,'previewLine'[b[text()="Hot stat:"]]/text)
You have made a great mix :)
Your locator is absolutely invalid.
Also, if you want to print the paragraph text without the "Hot streak" you will need to remove that string from the entire div (paragraph) text.
This should do what you are trying to achieve:
main = driver.find_element(By.XPATH,"//div[#class='previewLine' and ./b[text()='Hot streak']]").text
main = main.replace('Hot streak','')
print(main)
I'm not finding any text 'Hot stat:'. You'll have to attach the html code where you found that.
I assume that you want to retrieve the text of a specific previewLine?
main = driver.find_element(By.XPATH ,'//div[#class="previewLine"]/b[contains(text(),"Hot streak")]/..')
print(main.text)

Selenium action 'move_to_element' doesn't work in Safari because of usupported 'pause' command

The next command is failed on Safari browser during automation testing:
ActionChains(driver).move_to_element(searchInput).perform()
Exception:
InvalidArgumentException: Message: Encountered key input source with
invalid 'value' in payload: {actions = ({duration = 0;type =
pause;});
id = key;
type = key;}
The whole refined test example:
def test_safari2(self):
driver = webdriver.Safari()
driver.get('https://www.wikipedia.org')
locator = (By.ID, 'searchInput')
# 1. the line below is passed
searchInput = WebDriverWait(driver, timeout=30).until(expected_conditions.visibility_of_element_located(locator))
# 2. the line below is failed in Safari, but passed in Chrome, FF
ActionChains(driver).move_to_element(searchInput).perform()
However! If self.w3c_actions.key_action.pause() is commented inside action move_to_element(), then the whole Action chains works!
def move_to_element(self, to_element):
"""
Moving the mouse to the middle of an element.
:Args:
- to_element: The WebElement to move to.
"""
if self._driver.w3c:
self.w3c_actions.pointer_action.move_to(to_element)
# self.w3c_actions.key_action.pause()
else:
self._actions.append(lambda: self._driver.execute(
Command.MOVE_TO, {'element': to_element.id}))
return self
The similar situation with other actions.
My question is:
Is it is known limitation of Safari? And therefore ActionChais command could not be use for Selenium + Safari? Or there is some configuration pecularity?
My test runner configuration:
OS: Mac HighSierra 10.13.6
Safari 12.0 (13606.2.11)
Selenium: 3.14.1
Python: 2.7.14
Safari is started with w3c capabilities and protocol (i.e. driver.w3c=True)
Issue background:
I have an enough developed framework with a lot of actions and tests that work Ok for Chrome and Firefox. Now I'm trying to extend coverage for Safari browser also. So, that is why I'm searching for solution for not working ActionChains
Workaround by wrapping ActionChains class so that key_action.pause is not used (which does not seem to serve any important purpose):
import selenium.webdriver
class ActionChains(selenium.webdriver.ActionChains):
def __init__(self, driver):
super(ActionChains, self).__init__(driver)
if driver.name in ('Safari', 'Safari Technology Preview'):
self.w3c_actions.key_action.pause = lambda *a, **k: None