I'm new in Selenium with Python and I have a problem with ActionChains , that I couldn't understand.I want to click on an element and move it to another element with ActionChain , I tried 2 ways to do this .
Firstly the combination of 2 py-files , they don't work
import time
from selenium.webdriver.common.action_chains import ActionChains
def action_function(driver,start,des):
time.sleep(2)
ActionChains(driver).click_and_hold(start).move_to_element(des).release().perform()
time.sleep(3)
import time
import unittest
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from hilffunktionen import hilffunktion
class PythonOrgSearch(unittest.TestCase):
driver = webdriver.Firefox('./geckodriver')
#classmethod
def firsttest(self):
self.driver.get('file:///C:/My-Project/Probe/index.html')
time.sleep(5) # Let the user actually see something!
dragitem = self.driver.find_element_by_id('mydivheader')
print(dragitem.get_attribute('innerHTML'))
time.sleep(5)
destination = self.driver.find_element_by_id('destination')
time.sleep(4)
hilffunktion.action_function(self.driver,dragitem,destination)
time.sleep(3)
But if I try to write it direct in class , it works
import time
import unittest
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
class PythonOrgSearch(unittest.TestCase):
driver = webdriver.Firefox('./geckodriver')
driver.get('file:///C:/My-Project/Probe/index.html')
time.sleep(5) # Let the user actually see something!
dragitem = driver.find_element_by_id('mydivheader')
print(dragitem.get_attribute('innerHTML'))
time.sleep(5)
destination = driver.find_element_by_id('destination')
time.sleep(4)
ActionChains(driver).click_and_hold(dragitem).move_to_element(destination).release().perform()
time.sleep(3)
Could someone explain me why ? , If I just want to write it in the first way , what should I do , so that it works ? . I would be very thankful for you help
The second way "works" because
A class definition is an executable statement.
(see more in class-definitions)
Basically python runs the statements in class definition.
If you want to do the first way (assume that you want to use unittest), maybe you can define the firsttest method as test_xyz(self): ... and in the end you can call unittest.main(), similar in the basic example.
Related
I am trying to make a python program using selenium that opens the browser and does some stuff, waits for the user to click on a button, then selenium takes over again. I know that I am supposed to use an explicit wait but I do not know how to make selenium wait for the user to click a button on the browser before continuing with my code.
Here is a summary of my code so far:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
driver_path = my_driver_path
driver = webdriver.Chrome(executable_path=driver_path, chrome_options=options)
driver.get(my url)
... (Some code that does automation stuff until a certain point)
#What do I do here?
wait = WebDriverWait(driver, 10)
...(After the user clicks I want the program to resume)
Presumably, something on the website changes when the user clicks on the button. Define that change as the wait condition.
For example, if you expect an element to pop up:
def is_visible(by, identifier):
def condition(driver):
elems = driver.find_elements(by, identifier)
ele = elems and elems[0]
exists_and_displayed = ele and ele.is_displayed()
return exists_and_displayed
return condition
wait.until(is_visible(By.ID, 'added_or_unhidden_after_click'))
Or if you expect something to disappear:
def is_not(condition):
#ft.wraps(condition)
def wrapper(driver):
return not condition(driver)
return wrapper
wait.until(is_not(is_visible(By.ID, 'removed_or_hidden_after_click')))
(typed from memory, might have a syntax error or so, but you should get the idea)
(The built-in expected_conditions as EC basically do these same things, but I run into small issues with them here and there the way they're written, so I prefer to roll my own.)
I need to move an user with selenium to a list, I tried with drag and drop command but I cant do it, the only way that the platform lets me move a user to the list is by drag and drop it to list so
any help?
import email
from importlib.resources import path
from lib2to3.pgen2 import driver
import webbrowser
import unittest
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from time import sleep
path="C:\\Users\\ysarmiento\\Desktop\\PythonVsCode\\chromedriver.exe"
username="obviusly not gonna show"
password="same"
path="C:\\Users\\ysarmiento\\Desktop\\PythonVsCode\\chromedriver.exe"
driver = webdriver.Chrome(path)
driver.get("https://beanalyzer.teldat.com/login")
driver.maximize_window()
driver.find_element_by_id("email").send_keys(username)
driver.find_element_by_id("password").send_keys(password)
driver.find_element_by_xpath("/html/body/div/div[2]/div[1]/form/button").click()
sleep(3)
driver.get("https://beanalyzer.teldat.com/settings/system-provisioning")
target=driver.find_element_by_xpath('//*[#id="main-el"]/div[3]/div/div[2]')
value=driver.find_element_by_xpath('//*[#id="peculiar"]/div/div/div[1]')
actions=ActionChains(driver)
actions.drag_and_drop(target,value).perform()
sleep(4)
I have this and it doesn't give me any errors but it doesn't work, for locating the elements I'm using Xpath (cause some users and lists doesn't have an id or name)
I'm putting here the type of list and user(element) if needed
User Element
type of list
if you need something else let me know
thank you for your time
Unable to input values fully in a textbox field using send keys. Only partial values entered and no error shown.
Attempted sending keys with a wait.
Attempted sending keys slowly.
[Edit] - This is the entire script as requested in the comments below
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.wait import WebDriverWait
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
import time
from time import sleep
from selenium.webdriver.common.keys import
Keysdriver=webdriver.Chrome(executable_path="C:\Program Files (x86)\Drivers\chromedriver.exe")
driver.get("https://www.volunteers.ae/register.aspx")
driver.find_element_by_xpath("//*[#id='topnav_btnLangShift']").click()
driver.find_element(By.ID,'body_txtFName').send_keys("RADHIKA")
driver.find_element(By.ID,'body_txtLName').send_keys("PORANKI")
driver.find_element_by_id("body_txtEmail").send_keys("radhika.po#gmail.com")
element=driver.find_element_by_id("body_ddGender")
dropdown=Select(element)dropdown.select_by_value("Female")
driver.find_element_by_id("ctl00_body_txtDOB_dateInput").send_keys("08/04/1986")
element=driver.find_element_by_id("body_ddNationality")
dropdown=Select(element)
dropdown.select_by_value("India")
element=driver.find_element_by_id("body_ddCountryOfResidence")
dropdown=Select(element)
dropdown.select_by_value("+971")
element=driver.find_element_by_id("body_ddEmirate")
dropdown=Select(element)
dropdown.select_by_value("DUBAI")
time.sleep(10)
element=driver.find_element_by_id("body_ddCity")
dropdown=Select(element)
dropdown.select_by_value("DUBAI CITY")
def ClickAndSlowType(element, text):
element.click()
sleep(1) # let scripts run
for t in list(text):
print(t)
element.send_keys(t)
sleep (0.1)
mobile = WebDriverWait(driver, 8).until(ec.element_to_be_clickable((By.XPATH, "//*[#id='ctl00_body_txtEtisalat']")))
mobile.click()
mobile.send_keys("68862632")
What's the problem when you run your script?
I enhanced your script with a wait action and it works great:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('https://www.volunteers.ae/register.aspx')
mobile = WebDriverWait(driver, 8).until(EC.element_to_be_clickable((By.XPATH, "//*[#id='ctl00_body_txtEtisalat']")))
mobile.click()
mobile.send_keys("68862632")
Output looks like this:
There does seem to be some scripting at work in the page. Evertyime you click and type it resents the field. However, the above code still seems to work.
If there's a problem, let me know what's happening (with any relevant errors that occur) and i'll look again.
[Update!]
Based on the comments below, try typing with a delay.
Add this import:
from time import sleep
Add this function:
def ClickAndSlowType(element, text):
element.click()
sleep(1) # let scripts run
for t in list(text):
print(t)
element.send_keys(t)
sleep (0.1)
Run this:
mobile = WebDriverWait(driver, 8).until(EC.element_to_be_clickable((By.XPATH, "//*[#id='ctl00_body_txtEtisalat']")))
ClickAndSlowType(mobile, "68862632")
I can't recreate your issue but this also works for me so worth a try. It just types a bit slower in case of the funky in-page script issues.
Let me know how it goes.
If you can update your question with your entire i code i might be able to recreate and provide a tried and tested answer. (no one likes "it worked for me")
As it works locally but not on #Paul 's machine : we need to debug it . Try this at the end of the script and please tell exactly what you see happen to the field and what the output from the prints on the console:
def WaitForDocumentReadyState():
print("Ready State Before: " + driver.execute_script('return document.readyState'))
WebDriverWait(driver, 10).until(lambda driver: driver.execute_script('return document.readyState') == 'complete')
def ClickAndSlowType(element, text):
element.click()
WaitForDocumentReadyState()
sleep(1) # let scripts run
for t in list(text):
element.send_keys(t)
WaitForDocumentReadyState()
sleep (0.5)
sleep(1) # let scripts run
WaitForDocumentReadyState()
mobile = WebDriverWait(driver, 8).until(ec.element_to_be_clickable((By.XPATH, "//*[#id='ctl00_body_txtEtisalat']")))
#mobile.click()## REMOVED
#mobile.send_keys("68862632") ## REMOVED
ClickAndSlowType(mobile, "68862632") ## using the function
Good day.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
import time
def automation_func(url, i):
driver = webdriver.Chrome()
driver.maximize_window()
time.sleep(3)
driver.get("https://site.ru")
btn_elem1 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/ul/li[2]")
btn_elem1.click()
btn_elem2 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/p[1]/label/input")
btn_elem2.click()
btn_elem2.send_keys("login")
btn_elem3 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/p[2]/label/input")
btn_elem3.click()
btn_elem3.send_keys("pass")
btn_elem4 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/a")
btn_elem4.click()
time.sleep(3)
driver.get(url)
btn_elem5 = driver.find_element_by_xpath("/html/body/div[1]/div[3]/div[1]/fieldset/div[2]/img[1]")
btn_elem5.click()
time.sleep(5)
if "Даво" in driver.page_source:
screenshot = driver.save_screenshot("{i}.png")
def main():
for i in range(4, 12000):
automation_func(f"https://site.ru/lookup/{i}", i)
if __name__ == "__main__":
main()
Example above - everything works, but every time a new window opens. Everything is clear, because it is written in the function.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
import time
def main():
driver = webdriver.Chrome()
driver.maximize_window()
time.sleep(3)
driver.get("https://site.ru")
btn_elem1 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/ul/li[2]")
btn_elem1.click()
btn_elem2 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/p[1]/label/input")
btn_elem2.click()
btn_elem2.send_keys("login")
btn_elem3 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/p[2]/label/input")
btn_elem3.click()
btn_elem3.send_keys("pass")
btn_elem4 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/a")
btn_elem4.click()
def automation_func(url, i):
driver.get(url)
time.sleep(3)
btn_elem5 = driver.find_element_by_xpath("/html/body/div[1]/div[3]/div[1]/fieldset/div[2]/img[1]")
btn_elem5.click()
time.sleep(5)
if "Даво" in driver.page_source:
screenshot = driver.save_screenshot("{i}.png")
def main():
for i in range(4, 12000):
automation_func(f"https://site.ru/lookup/{i}", i)
if __name__ == "__main__":
main()
Here I wanted to display it separately. So that the function contains only what is needed. To prevent many windows from opening. Since you have to go over more than 10 thousand pages. Gives an error message.
There is always one mistake. driver and main are underlined. If you put different indents, then something gets better there, then another error. In general, it already seems to have gone through all the options.
Undefined variable 'driver'
Undefined variable 'driver'
Undefined variable 'driver'
Undefined variable 'driver'
function already defined line 9
Unused variable 'screenshot'
There is also a suspicion that the screenshot does not work. Or I didn't find the path where the images are saved.
Few things for you to consider:
You have two main() functions.
When you execute the script and try to call main(), which one do you expect to be called?
I suggest you rename the first one after it's purpose (e.g. CreateDriver or SetUpWedriver or such)
Your automation_func() has no context of driver. That's why you'll be getting so many undefined errors around it.
In your first main (the one to rename) you have
def main():
driver = webdriver.Chrome()
...
That line initialises the variable called "driver". That variable only exists in the context of that function. Once the function finishes all the variables are destroyed to release the memory.
Compare that to your first block of code where all the actions are done in a single block of code - therefore they all know what driver is.
With that variable-context in mind consider that you have:
def automation_func(url, i):
driver.get(url)
How will this function know what driver is? It has not been initiated.
The answer to this is to declare the variable outside the function - this makes it accessible everywhere.
Top of your script will look like this:
#...other imports
from selenium.webdriver.common.action_chains import ActionChains
import time
driver = webdriver.Chrome()
#note - renamed! - used to be main()
def CreateDriver():
driver.maximize_window()
time.sleep(3)
#rest of code below
Finally - The site you provide in the code doesn't work for me. That means i can't fully test it, but putting the above pieces together, I think you might want this:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
import time
#Note - moved outside the functions so it's accessible to all
driver = webdriver.Chrome()
#note - renamed! - this is not responsible for setting up the driver
def CreateDriver():
driver.maximize_window()
time.sleep(3)
driver.get("https://site.ru")
btn_elem1 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/ul/li[2]")
btn_elem1.click()
btn_elem2 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/p[1]/label/input")
btn_elem2.click()
btn_elem2.send_keys("login")
btn_elem3 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/p[2]/label/input")
btn_elem3.click()
btn_elem3.send_keys("pass")
btn_elem4 = driver.find_element_by_xpath("/html/body/div[2]/div[3]/div[2]/div[1]/div/div[2]/div/a")
btn_elem4.click()
def automation_func(url, i):
CreateDriver # this gets the driver into the state we want
driver.get(url)
time.sleep(3)
btn_elem5 = driver.find_element_by_xpath("/html/body/div[1]/div[3]/div[1]/fieldset/div[2]/img[1]")
btn_elem5.click()
time.sleep(5)
if "Даво" in driver.page_source:
screenshot = driver.save_screenshot("{i}.png")
def main():
for i in range(4, 12000):
automation_func(f"https://site.ru/lookup/{i}", i)
if __name__ == "__main__":
main()
Last note - your additional question: Your screenshot does work.
You're not specifying a path, so when your code reaches that point it creates the screenshot in the same directory as the python file that is being executed.
If you're not seeing the screenshot, it's most likely because that line of code hasn't run yet or your IF function doesn't meet the right condition.
In Selenium Webdriver, I am looking to be able to take a full page screenshot using FireShot executed from a Python script.
I have the following code so far:
import unittest
import execjs
from execjs import get
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
from selenium.webdriver.common.keys import Keys
class PythonOrgSearc(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome('/usr/bin/chromedriver');
def test_login_and_make_payment_on_account(self):
driver = self.driver;
driver.set_window_size(1024,768);
# Log in to My Account
driver.get("https://www.mywebsite.com");
self.assertIn("Sign In", driver.title);
driver.save_screenshot('/Users/username/Documents/Selenium_Test/01a_login.png');
# Enter username
user = driver.find_element_by_id("EmailOrAccountNumber");
user.send_keys("user#me.co.uk");
# Enter password and submit form
password = driver.find_element_by_id("Password");
password.send_keys("password123");
driver.save_screenshot('/Users/username/Documents/Selenium_Test/01b_login_filled.png');
password.send_keys(Keys.RETURN);
# Confirm logged into My Account
self.assertIn("Account Summary", driver.title);
driver.save_screenshot('/Users/username/Documents/Selenium_Test/02a_My_Account.png');
def tearDown(self):
self.driver.close();
if __name__ == "__main__":
unittest.main();
I have installed PyExecJS, but have no idea how I can begin using the FireShot API to replace the current save_screenshot functions used in the code. Thank you for any steer or guidance you can provide.
I think it is better to use driver.execute_script command to execute your javascript in the browser, but if you want to check a markup, perhaps, applitools could help you