SendMouseWheelEvent does not work on subsequent page loads - python

I'm trying to use SendMouseWheelEvent to pass mouse scrolls into the browser, but it is only working on the first page load. Any subsequent pageloads after that, it does not work, unless the browser is interferred with actual mouse scroll.
I've prepared the following script. The "errorrep" is actually the name of the script itself, as "errorrep.py", into which I'm assigning the browser as "mybrowser".
How can I have the browser correctly work with SendMouseWheelEvent on subsequent pageloads?
cefpython version is 66.1.
"""
SendMouseWheelEvent is correctly performed on the first page load. On any pageloads after that, it does not seem to work, but it works again when the actual mouse device performs a scroll on the webpage
'# test 1' which does a javascript code 'scrollBy', works on every pageload.
'# test 2' which does a SendMouseWheelEvent, only works on first page load.
"""
from cefpython3 import cefpython as cef
import time
from threading import Thread
import errorrep
mybrowser = None
def main():
cef.Initialize()
browser = cef.CreateBrowserSync(url="https://stackoverflow.com/")
browser.SetClientHandler(LoadHandler())
errorrep.mybrowser = browser
cef.MessageLoop()
del browser
cef.Shutdown()
class LoadHandler(object):
def OnLoadingStateChange(self, browser, is_loading, **_):
if not is_loading:
Thread(target=test).start()
def test():
print("Page loading is complete!")
for i in range(5):
print('scrolling')
# test 1
errorrep.mybrowser.ExecuteJavascript(jsCode="""scrollBy(0,25)""")
# test 2
# errorrep.mybrowser.SendMouseWheelEvent(0,0,0,-120, cef.EVENTFLAG_NONE)
time.sleep(1)
print('opening new page, clicking on the logo link')
errorrep.mybrowser.ExecuteJavascript(jsCode="""document.getElementsByClassName('s-topbar--logo js-gps-track')[0].click();""")
if __name__ == '__main__':
main()

Related

Selenium Webdriver python showing error soon after it executes the code

When I run my python script which is supposed to open github in edge browser, it works, but closes soon after it is done
#imports
from selenium import webdriver
from selenium.webdriver.edge.service import Service
# Change the directory
#Github
def github():
browser = webdriver.Edge(r'C:\Program Files\Browser Drivers\Edge Drivers\msedgedriver.exe')
browser.get("https://github.com")
if __name__ == "__main__":
github()
The error
DevTools listening on ws://127.0.0.1:52908/devtools/browser/7ebfcee1-74f9-43ba-bf79-
99549f4d7ccf
[2916:7184:0428/150623.910:ERROR:fallback_task_provider.cc(124)] Every renderer should have at
least one task provided by a primary task provider. If a "Renderer" fallback task is shown, it
is a bug. If you have repro steps, please file a new bug and tag it as a dependency of
crbug.com/739782.

Python - Selenium - Single thread to multiple threads

I have an automation project made with Python and Selenium which I'm trying to make it run with multiple browsers in parallel.
The current workflow:
open a browser for manual login
save cookies for later use
in a loop, open additional browsers, load the saved session in each newly opened browser
The described workflow is opening some browsers, one by one, until all required browsers are opened.
My code contains several classes: Browser and Ui.
The object instantiated with Ui class contains a method which at some point executes the following code:
for asset in Inventory.assets:
self.browsers[asset] = ui.Browser()
# self.__open_window(asset) # if it is uncommented, the code is working properly without multi threading part; all the browsers are opened one by one
# try 1
# threads = []
# for asset in Inventory.assets:
# threads.append(Thread(target=self.__open_window, args=(asset,), name=asset))
# for thread in threads:
# thread.start()
# try 2
# with concurrent.futures.ThreadPoolExecutor() as executor:
# futures = []
# for asset in Inventory.assets:
# futures.append(executor.submit(self.__open_window, asset=asset))
# for future in concurrent.futures.as_completed(futures):
# print(future.result())
The problem appear when self.__open_window is executed within a thread. There i get an error related to Selenium, something like: 'NoneType' object has no attribute 'get', when self.driver.get(url) is called from the Browser class.
def __open_window(self, asset):
self.interface = self.browsers[asset]
self.interface.open_browser()
In class Browser:
def open_browser(self, driver_path=""):
# ...
options = webdriver.ChromeOptions()
# ...
#
web_driver = webdriver.Chrome(executable_path=driver_path, options=options)
#
self.driver = web_driver
self.opened_tabs["default"] = web_driver.current_window_handle
#
# ...
def get_url(self, url):
try:
self.driver.get(url) # this line cause problems ...
except Exception as e:
print(e)
My questions are:
Why do i have this issue in a multi threading environment?
What should i do in order to make the code work properly?
Thank You
I found the mistake, it was because of a wrong object reference.
After modification the code is working well.
I updated the following lines at __open_window:
def __open_window(self, asset, browser):
browser.interface = self.browsers[asset]
browser.interface.open_browser()
and in # try 1 code section:
threads.append(Thread(target=self.__open_window, args=(asset, browser, ), name=asset))

Python tkinter - Button with command lamba: doesn't work

I wrote this script with Python tkinter and Selenium.
I create a button, when we click on it, 2 functions have to be executed. But I don't know why, it doesn't work well, only the first one: login() is executed and the second one: kalk() will not be executed.
If I put all the lines of the 2 functions in only one function, it works until the end without any problem.
Why does the below code not work ?
Here is the code (only a part of the program):
def login():
boutoncount.config(state='disabled')
browser = webdriver.Chrome(executable_path=r"C:\Users\Bat02\Desktop\Python\Selenium Test\chromedriver.exe")
browser.get('url')
time.sleep(10)
login= browser.find_element_by_id("UserID")
pwd = browser.find_element_by_id("Password")
confirm= browser.find_element_by_id("LogIn")
login.send_keys(loginentry.get())
pwd.send_keys(pwdentry.get())
time.sleep(3)
confirm.click()
def kalk():
time.sleep(10)
kalknum= browser.find_element_by_id("txt_Kalk")
eigkalkuncheck=browser.find_element_by_id("chk_Kalk")
eigkalkuncheck.click()
kalknum.send_keys(user_entries[0].get())
boutoncount=Button(fenetre,text="count",width=800,height=1,bg="white", font="bold",bd=5, command=lambda:[login(),kalk()])
boutoncount.pack(side=BOTTOM)
Thank you !

Pycharm,Selenium Process finished with exit code zero [duplicate]

This question already has an answer here:
Selenium with Python-unittest - Test returns Process finished with exit code 0 and no action is performed
(1 answer)
Closed 3 years ago.
When i'am trying to run my code though Pycharm it doesnt execute anything. Normally it should run code and Chrome should start.
1) Tried to run from Terminal still the same.
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.keys import Keys
import time
import unittest
class SearchText(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
self.driver.get('http://book.theautomatedtester.co.uk/')
self.driver.maximize_window()
time.sleep(2)
self.driver.switch_to_window(driver.window_handles[0])
def test_search_by_text(self):
self.driver.find_element_by_xpath('/html/body/div[2]/ul/li[1]/a').click()
self.driver.find_element_by_id('radiobutton').click()
self.driver.find_element_by_id('selecttype').send_keys('Selenium Code',Keys.ENTER)
self.driver.find_element_by_name('selected(1234)').click()
self.driver.find_element_by_id('storeinput').send_keys('Salamlar')
self.driver.find_element_by_id('secondajaxbutton').click()
self.driver.find_element_by_id('multiplewindow').click()
self.driver.switch_to_window(driver.window_handles[1])
self.driver.find_element_by_id('closepopup').click()
self.driver.switch_to_window(driver.window_handles[0])
self.driver.find_element_by_id('loadajax').click()
self.driver.find_element_by_id('ajaxdiv')
assert driver.page_source.find('The following text has been loaded from another page on this site. It has been loaded in')
aka = driver.find_element_by_id('verifybutton')
if aka.is_enabled():
aka.click()
else: print('Not Existing')
def tearDown(self):
# close the browser window
self.driver.quit()
Expected Result: Code will trigger Browser and will run test
Your code does not actually execute anything.
If you want to execute the unittest you have to call unittest.main(). And since this should only be done when executing the file itself, you should add this at the bottom of your file.
if __name__ == '__main__':
unittest.main()

How to enable selenium webdriver to work with Python remote objects (Pyro) in a bokeh document?

I have a python document running in bokeh server with bokeh serve view_server_so.py --show. The webpage is immediately opened in a browser tab.
For testing purposes I am using Pyro to allow remote access to some of the objects / methods running in the bokeh server.
My server testscript creates just one button and one method (exposed to remote control), bokeh serves the webpage on http://localhost:5006/view_server_so.
The button is a Toggle button, each time the button is pressed its active state alternates between True and False, and its color changes.
# view_server_so.py
# This script shall be started from the command line with
# bokeh serve view_server_so.py --show
from bokeh.layouts import layout, row
bokeh.models import Toggle
from bokeh.io import curdoc
import os
import Pyro4
import socket
import subprocess
import threading
# The layout used in the html-page
class View():
def __init__(self):
self.document = curdoc()
self.btn_task = Toggle(label="Press me",
button_type="success",
css_classes=["btn_task"])
self.layout = layout(row(self.btn_task))
#Pyro4.expose
def get_btn_task_active_state(self):
# This method is enabled for remote control
# The btn_task changes its active state each time it is pressed (bool)
print('active state: {}'.format(self.btn_task.active))
return self.btn_task.active
# As the script is started with 'bokeh serve',
# bokeh has control of the main event loop.
# To enable Pyro to listen for client requests for the object view,
# and its exposed method,
# the Pyro event loop needs to run in its own thread.
class PyroDaemon(threading.Thread):
def __init__(self, obj):
threading.Thread.__init__(self)
self.obj=obj
self.started=threading.Event()
print('PyroDaemon.__init__()')
def run(self):
daemon=Pyro4.Daemon()
obj = self.obj
self.uri=daemon.register(obj,"test")
self.started.set()
print('PyroDaemon.run()')
daemon.requestLoop()
view = View()
print('view created')
# starting a Pyro name server
hostname = socket.gethostname()
print('hostname: {}'.format(hostname))
try:
print('try Pyro4.locateNS()')
name_server=Pyro4.locateNS()
except Pyro4.errors.NamingError:
print('except Pyro4.errorsNamingError')
args = ['python', '-m', 'Pyro4.naming', '-n', hostname]
p = subprocess.Popen(args)
name_server=Pyro4.locateNS()
print('Nameserver is started')
# create a pyro daemon with object view, running in its own worker thread
pyro_thread=PyroDaemon(view)
pyro_thread.setDaemon(True)
pyro_thread.start()
pyro_thread.started.wait()
print('Daemon is started')
# The object view is registered at the Pyro name server
name_server.register('view', pyro_thread.uri, metadata = {'View'})
print('view is registered')
view.document.add_root(view.layout)
Now I have a second testscript. After some setup for the remote object, it simply calls several times the method get_btn_task_active_state() and prints the result. When between the calls the button is clicked in the browser, the active state switches and is correctly printed.
import Pyro4
import time
# looking for the Pyro name server created in view_server_so.py
nameserver=Pyro4.locateNS(broadcast = True)
# get the URI (universal resource identifier)
uris = nameserver.list(metadata_all = {'View'})
# create a proxy object that interacts (remote control)
# with the remote object 'view'
view_rc = Pyro4.Proxy(uris['view'])
for i in range(3):
time.sleep(3)
# change the state manually: click on the button
print('state: {}'.format(view_rc.get_btn_task_active_state()))
# prints
# state: False
# state: True
# state: False
As manual testing gets tedious, I want to automate the manual clicks to the button. So I am adding webdriver support, look up the button in the webpage, and have some automated clicks and the calls to get_btn_task_active_state() as before.
import Pyro4
from selenium import webdriver
import socket
import time
# looking for the Pyro name server created in view_server_so.py
nameserver=Pyro4.locateNS(broadcast = True)
# get the URI (universal resource identifier)
uris = nameserver.list(metadata_all = {'View'})
# create a proxy object that interacts (remote control)
# with the remote object 'view'
view_rc = Pyro4.Proxy(uris['view'])
# use the Chrome webdriver
driver = webdriver.Chrome()
# open a Chrome Browser and the given webpage
driver.get("http://localhost:5006/view_server_so")
time.sleep(1)
# Find the button
btn_task = driver.find_element_by_class_name("btn_task")
for i in range(3):
time.sleep(1)
print('state: {}'.format(view_rc.get_btn_task_active_state()))
btn_task.click()
# prints
# state: False
# state: False
# state: False
#
# but should alternate between False and True
An webdriver controlled browser opens, I can see the color of the button change visually as it is automatically clicked, but the active state of the button does not seems to change any more.
What changes would be necessary, so that the automated script gives the same results as the manual testing?

Categories