Selenium Bot: Irregular Switching of Windows - selenium

Once I'm clicking the element More Information, the link is getting clicked and then the window is jumping back to it's previous window and a TimeoutException is being shown.
Code:
self.driver.window_handles
base = "https://outlook.office.com/mail/inbox/id/AAQkADQ0ZmY1YmRkLWExNDEtNGNlYS1iOTZmLTVmNzNjMzhkNjUyMgAQAJmE%2FyrhD0supMphUUSGrmQ%3D"
window_set = {self.driver.window_handles[0], self.driver.window_handles[1]}
for x in window_set:
if(base != x):
self.driver.maximize_window()
wait = WebDriverWait(self.driver, 10)
self.driver.switch_to.window(x)
frame = wait.until(EC.presence_of_element_located((By.NAME, "mainFrame")))
self.driver.switch_to.frame(frame)
element = wait.until(EC.element_to_be_clickable((By.ID, "mc-lnk-moreInfo")))
element.click()
Please HELP!
WebPage Image:(contains both the tabs)
In this image More Information has been clicked and has changed to Less Information

This did the job!
self.driver.window_handles
wait = WebDriverWait(self.driver, 10)
base = self.driver.window_handles[0]
child = self.driver.window_handles[1]
windows = {self.driver.window_handles[0], self.driver.window_handles[1]}
for x in windows:
if(base != x):
self.driver.switch_to.window(x)
frame = wait.until(EC.presence_of_element_located((By.NAME, "mainFrame")))
self.driver.switch_to.frame(frame)
element = wait.until(EC.element_to_be_clickable((By.ID, "mc-lnk-moreInfo")))
element.click()

Related

How do I delay the execution of a function within tkinter button command

I am trying to simulate a computer player "clicking" a button after a human user clicks a button In a grid of buttons. If I use the .after method the 'state' of the button change is delayed but it executes my check_state() method which doesn't detect the change. When I try time.sleep() method it prolongs the human click but still immediately invokes the 'auto' click regardless of where I put it in my code. I want a delay between the human click and 'auto' click.
I have tried widget.after(1000) which gives the desired delay of 'auto' click, but doesn't allow my the change to be seen by my check_state() function. I have tried time.sleep() which delays the execution of the human button click but the 'auto' click is still immediately invokes regardless of which order I place the sleep() function in relation to the call to auto_click(). I know there are better practices for this code implementation like using class based structure which I plan on using once my logic and functionality issues are resolved. My code is as follows:
import tkinter as tk
import random
def app():
def auto_click():
grid_state = get_grid_state()
possible_clicks = []
for i in range(0, len(grid_state)):
if grid_state[i] == " ":
possible_clicks.append(i)
#debug.config(text=possible_moves)
click = random.choice(possible_clicks)
buttons[click].after(1000, lambda: buttons[click].config(text = "auto", state=tk.DISABLED))
#time.sleep(1)
check_grid_state()
check_grid_full()
debug.config(text="test")
def onclick(*arg):
global is_full
buttons[arg[0]].config(text = "clicked", state=tk.DISABLED)
check_grid_state()
check_grid_full()
if not is_full:
auto_click()
def check_grid_full():
global is_full
result=[]
for i in range(len(buttons)):
result.append(buttons[i].cget('state'))
r = [*set(result)]
if r == ['disabled']:
is_full = True
grid_status.config(text=is_full)
else:
is_full = False
Retrieve the current state of the grid
def get_grid_state():
grid_state =[]
for i in range(len(buttons)):
grid_state.append(buttons[i].cget('text'))
return grid_state
Check grid state
def check_grid_state():
grid_states.config(text=get_grid_state())
Global Variables
is_full = False
buttons = []
c=0
Window
root = tk.Tk()
root.title("Title")
Heading
label = tk.Label(root, text="grid state", font = ("Ariel black",22, "bold"))
label.pack()
Grid Frame
frame = tk.Frame(root)
frame.pack()
for row in range(3):
for column in range(3):
buttons.append(tk.Button(frame, text=f" ", font=("arial", "22"), state=tk.ACTIVE, height=2, width=2, command=lambda c=c: onclick(c)))
buttons[c].grid(row=row, column=column)
c += 1
Status bar
grid_states = tk.Label(root, text=f"")
grid_states.pack()
grid_status = tk.Label(root, text=f"")
grid_status.pack()
#btn_is = tk.Label(root, text=f"")
#btn_is.pack()
Debugging output label
debug = tk.Label(root, text="debug")
debug.pack()
Event loop
root.mainloop()
if name == "main":
app()

Selenium - clicked windows does not open & no error

My code:
#Open Website
profile_path = r'C:\Users\XXX\AppData\Local\Mozilla\Firefox\Profiles\ndefault-release'
options = Options()
options.binary_location = r'C:\Program Files\Mozilla Firefox\firefox.exe'
options.set_preference('profile', profile_path)
options.add_argument("--no-sandbox")
service = Service(r'C:\Users\XXX\geckodriver.exe')
driver = Firefox(service=service, options=options)
# declaration of variables
name = "x"
suffix = "x"
start_number = 1
end_number = 1000
for i in range(start_number, end_number):
driver.get('https://www.bauhaus.info/gewinnspiel')
time.sleep(3)
#driver.find_element(by=By.XPATH, value=f"/div/div/div/div/div[2]/div/div[2]/div/div/div/button").click()
element = driver.execute_script("""return document.querySelector('#usercentrics-root').shadowRoot.querySelector("button[data-testid='uc-accept-all-button']")""")
element.click()
time.sleep(1)
driver.switch_to.frame(0)
time.sleep(1)
driver.find_element(by=By.XPATH, value=f"/html/body/section/div/div/div/div[2]/div/div/div[1]/div[1]/form/div/div[3]/a").click()
time.sleep(2)
If i add the xpath in the firefox console i get the right output:
Array [ a.btn.btn-primary ]
But the white windows does not open, only if i click manually on it:
shadow_host = driver.find_element(By.ID, "usercentrics-root")
if driver.name == 'firefox':
shadow_root = driver.execute_script('return arguments[0].shadowRoot.children', shadow_host)[0]
else:
shadow_root = shadow_host.shadow_root
WebDriverWait(shadow_root, 30).until(EC.presence_of_element_located((By.CSS_SELECTOR, "button[data-testid='uc-accept-all-button']"))).click()
iframe = WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.CSS_SELECTOR, "iframe[title=' blackweekgewinnspiel']")))
driver.switch_to.frame(iframe)
canvas = driver.find_element(By.CSS_SELECTOR, "canvas")
driver.execute_script("arguments[0].scrollIntoView(true);",canvas)
driver.execute_script("arguments[0].click();", canvas);
driver.switch_to.default_content()
Two points to note:
the Accept Cookies popup is in shadow DOM, for which Chrome + Selenium 4.1 has a ready made solution, but Firefox will also work with Selenium 4 via execute_script.
the roulette wheel is in an iframe, so must switch there before clicking.

Unable to locate element : xpath

I have made a youtube automation bot. I am getting error : unable to locate element (for the Xpath of subscribe button)
here is my code
from selenium import webdriver
from selenium import common
from selenium.webdriver.common import keys
from webdriver_manager.firefox import GeckoDriverManager
import time
class actions:
def __init__(self, email, password):
self.email = email
self.password = password
profile = webdriver.FirefoxProfile()
profile.set_preference("dom.webdriver.enabled", False)
profile.set_preference('useAutomationExtension', False)
profile.update_preferences()
driver = webdriver.Firefox(
executable_path=GeckoDriverManager().install(), firefox_profile=profile)
self.bot = driver
# self.bot.maximize_window()
self.bot.set_window_size(400, 700)
self.is_logged_in = False
def login(self):
bot = self.bot
bot.get("https://accounts.google.com/signin/v2/identifier?service=youtube&uilel=3&passive=true&continue=https%3A%2F%2Fwww.youtube.com%2Fsignin%3Faction_handle_signin%3Dtrue%26app%3Ddesktop%26hl%3Den%26next%3Dhttps%253A%252F%252Fwww.youtube.com%252F&hl=en&ec=65620&flowName=GlifWebSignIn&flowEntry=ServiceLogin")
time.sleep(5)
try:
email = bot.find_element_by_name('identifier')
except common.exceptions.NoSuchElementException:
time.sleep(5)
email = bot.find_element_by_name('identifier')
email.clear()
email.send_keys(self.email + keys.Keys.RETURN)
time.sleep(5)
try:
password = bot.find_element_by_name('password')
except common.exceptions.NoSuchElementException:
time.sleep(5)
password = bot.find_element_by_name('password')
password.clear()
password.send_keys(self.password + keys.Keys.RETURN)
time.sleep(5)
self.is_logged_in = True
def kill(self):
bot = self.bot
bot.quit()
def subscribe(self, url):
if not self.is_logged_in:
return
bot = self.bot
bot.get(url)
time.sleep(4)
try:
value = bot.find_element_by_xpath(
'/html/body/ytd-app/div/ytd-page-manager/ytd-watch-flexy/div[5]/div[1]/div/div[7]/div[2]/ytd-video-secondary-info-renderer/div/div/div/ytd-subscribe-button-renderer/tp-yt-paper-button').get_attribute('aria-label')
value = value.split()
except:
bot.execute_script(
'window.scrollTo(0,document.body.scrollHeight/3.5)')
time.sleep(3)
value = bot.find_element_by_xpath(
'/html/body/ytd-app/div/ytd-page-manager/ytd-watch-flexy/div[5]/div[1]/div/div[7]/div[2]/ytd-video-secondary-info-renderer/div/div/div/ytd-subscribe-button-renderer/tp-yt-paper-button').get_attribute('aria-label')
value = value.split(':')
if value[0] == "Subscribe":
try:
bot.find_element_by_xpath(
'/html/body/ytd-app/div/ytd-page-manager/ytd-watch-flexy/div[5]/div[1]/div/div[7]/div[2]/ytd-video-secondary-info-renderer/div/div/div/ytd-subscribe-button-renderer/tp-yt-paper-button').click()
time.sleep(3)
except:
bot.execute_script(
'window.scrollTo(0,document.body.scrollHeight/3.5)')
time.sleep(3)
bot.find_element_by_xpath(
'/html/body/ytd-app/div/ytd-page-manager/ytd-watch-flexy/div[5]/div[1]/div/div[7]/div[2]/ytd-video-secondary-info-renderer/div/div/div/ytd-subscribe-button-renderer/tp-yt-paper-button').click()
time.sleep(3)
how can i resolve this issue. I am not able to understand where things are going wrong. Or i should try find elements by id or other ways instead of Xpath.
Or is there any problem with any software.
Please help me out
Always use relative XPath in your test. Using the absolute XPath will cause regular test failures.
Refer to this tutorial about writing the relative XPaths. https://www.guru99.com/xpath-selenium.html
This extension will help you to write the relative XPaths. https://chrome.google.com/webstore/detail/chropath/ljngjbnaijcbncmcnjfhigebomdlkcjo
You can refer how to write XPath in different ways using functions like text(), starts-with(), contains(). so you can locate them by visible texts also.
Refer this articlehere

Selenium searching for ID not allways working?

In the past i often run in problems when a website is "lazy loading" -
It helped when i used such a search for the id
element = driver.find_element_by_id ("analyst-estimate")
driver.execute_script ("arguments[0].scrollIntoView();", element)
now i saw that this is not working for every site
on the following site everything works fine:
link = "https://www.gurufocus.com/stock/AAPL/summary"
options = Options ()
options.add_argument ('--headless')
options.add_experimental_option ('excludeSwitches', ['enable-logging'])
path = os.path.abspath (os.path.dirname (sys.argv[0]))
if platform == "win32": cd = '/chromedriver.exe'
elif platform == "linux": cd = '/chromedriver_linux'
elif platform == "darwin": cd = '/chromedriver'
driver = webdriver.Chrome (path + cd, options=options)
driver.get (link) # Read link
time.sleep (2) # Wait till the full site is loaded
element = driver.find_element_by_id ("analyst-estimate")
driver.execute_script ("arguments[0].scrollIntoView();", element)
time.sleep (1)
but on another site (also with an id - it is not working at all)
link = "https://finance.yahoo.com/quote/MSFT/analysis?p=MSFT"
options = Options ()
options.add_argument ('--headless')
options.add_experimental_option ('excludeSwitches', ['enable-logging'])
path = os.path.abspath (os.path.dirname (sys.argv[0]))
if platform == "win32": cd = '/chromedriver.exe'
elif platform == "linux": cd = '/chromedriver_linux'
elif platform == "darwin": cd = '/chromedriver'
driver = webdriver.Chrome (path + cd, options=options)
driver.get (link) # Read link
time.sleep (2) # Wait till the full site is loaded
element = driver.find_element_by_id ("YDC-Col1")
# element = driver.find_element_by_id ("Col2-4-QuoteModule-Proxy")
# element = driver.find_element_by_id ("app")
driver.execute_script ("arguments[0].scrollIntoView();", element)
time.sleep (1)
Why is this not working for the second website?
Its the exact same code - why is he not finding the id - it exists on the webpage?
There is a accept cookies pop up displayed before the page is loaded you have to click that first :
WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.NAME, "agree"))).click()
WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.ID, "YDC-Col1")))
Before testing something in headless check in non headless mode to see the actual behavior , and aif it fails only in headless take a screenshot to know the state of the website during the failure.
you can take screen shot as :
try:
link = "https://finance.yahoo.com/quote/MSFT/analysis?p=MSFT"
options = ChromeOptions()
options.add_argument('--headless')
options.add_experimental_option('excludeSwitches', ['enable-logging'])
driver = webdriver.Chrome(options=options)
driver.get(link) # Read link
time.sleep(2) # Wait till the full site is loaded
element = driver.find_element_by_id("YDC-Col1")
# element = driver.find_element_by_id ("Col2-4-QuoteModule-Proxy")
# element = driver.find_element_by_id ("app")
driver.execute_script("arguments[0].scrollIntoView();", element)
time.sleep(1)
except:
driver.get_screenshot_as_file("a.jpeg")
Time.sleep() isn't very stable for waiting for page loads. Switch over to webdriver waits. Also it doesn't seem to take 2 seconds to load.
wait = WebDriverWait(driver, 5)
wait.until(EC.presence_of_element_located((By.ID, "YDC-Col1")))
Also another issue could be using headless and not setting window size.
options.add_argument('--headless')
options.add_argument("--window-size=1920,1080")
Import
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

Selenium close alert in whatsapp bot

There is a bot that sends a message to numbers from a text file, but after switching to another person, there is an alert that needs to be confirmed.
However, it occurs when you open the next chat, and the alert processing goes the next line, but the code does not move further because it is waiting for the page to open. And I don't understand how to process these two cases at the same time
code:
def acceptAlert(driver):
try:
wait3 = WebDriverWait(driver, 10)
Alert = wait3.until(expected_conditions.alert_is_present())
if Alert is not None:
driver.switchTo().alert().dismiss()
except:
driver.get('https://web.whatsapp.com/send?phone=7' +
str(e[1:]) + '&test=sdfsdf')
time.sleep(5)
driver = webdriver.Chrome('C:\\Users\Marsel\AppData\Local\Programs\Python\Python38-32\chromedriver.exe')
test = open('base.txt', 'r')
lines = test.readlines()
i = 0
driver.get('https://web.whatsapp.com/send?phone=' + str(lines[i]) + '&test=sdfsdf')
time.sleep(15)
s = lines[i]
s = re.sub(r"[()'+']", "", s)
e = s.replace('-', '')
driver.get('https://web.whatsapp.com/send?phone=7' +
str(e[1:]) + '&test=sdfsdf')
time.sleep(5)
while i < len(lines):
driver.find_element_by_xpath('/html/body/div[1]/div/div/div[4]/div/footer/div[1]/div[2]/div/div[2]').send_keys('привет')
time.sleep(1)
driver.find_element_by_xpath(
'/html/body/div[1]/div/div/div[4]/div/footer/div[1]/div[2]/div/div[2]').send_keys(Keys.RETURN)
s = lines[i]
s = re.sub(r"[()'+']", "", s)
i += 1
acceptAlert(driver)
You should split them into separate functions and add try catch blocks.
def acceptAlert(driver):
try:
wait3 = WebDriverWait(driver, 10)
Alert = wait3.until(expected_conditions.alert_is_present())
if Alert is not None:
driver.switchTo().alert().accept()
except:
print('No alert found')
And then call this method inside your code loop. So when there is no alert, it will wait for 10 seconds and still continue execution even if there is no alert.