unable to locate ImageView element from android in appium (python) - python-2.7

I am trying to find highlighted button in below screenshot of uiautomatorviewer. I am using id of that element, but code gives me NoSuchElementException. I tried using class too but no luck. What's wrong?
uiautomatorviewer screenshot-
code(please check comment for the exact line which gives error)-
import os
from time import sleep
import unittest
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC # available since 2.26.0
from appium.webdriver.common.touch_action import TouchAction
# Returns abs path relative to this file and not cwd
PATH = lambda p: os.path.abspath(
os.path.join(os.path.dirname(__file__), p)
)
class SimpleAndroidTests(unittest.TestCase):
def setUp(self):
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '7.0'
desired_caps['deviceName'] = 'mishra'
desired_caps['app'] = PATH(
'Shopronto.apk'
)
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
#def tearDown(self):
# end the session
#self.driver.quit()
def test_01_correct_username_correct_password(self):
print "test1"
Wait = WebDriverWait(self.driver, 10)
login_tab=Wait.until(EC.presence_of_element_located((By.ID, "com.shopronto.customer:id/tvLogin")))
login_tab.click()
email = self.driver.find_element_by_id("com.shopronto.customer:id/etEmail")
email.send_keys("user1#gmail.com")
password = self.driver.find_element_by_id("com.shopronto.customer:id/etPwd")
password.send_keys("user123")
self.driver.back()
login = self.driver.find_element_by_id("com.shopronto.customer:id/tvBottomBtn")
login.click()
Wait.until(EC.presence_of_element_located((By.ID, "com.android.packageinstaller:id/permission_allow_button"))).click()
#below line gives error
self.driver.find_element_by_id("com.shopronto.customer:id/ivCategory")
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(SimpleAndroidTests)
unittest.TextTestRunner(verbosity=2).run(suite)
When I replace this-
self.driver.find_element_by_id("com.shopronto.customer:id/ivCategory")
with-
mylist=[]
self.driver.back()
mylist = self.driver.find_elements(By.XPATH, "//android.widget.ImageView")
The code keeps running without giving any output (for over 15 mins).
I have also tried this-
Wait.until(EC.presence_of_element_located((By.XPATH, "//android.widget.ImageView[#index='0']"))).click()
But no luck.

I think your all image view's have same ID, So you should use find element by xpath with index as there is no text with image view.

Related

Django - Whatsapp Sessions for scheduled messages

I'm developing a system where users, in addition to all the bureaucratic part, can register their clients' whatsapp so that automatic billing messages, congratulations, etc. are sent. Where the user would read the QR code and the system would be in charge of sending messages over time, using the user's whatsapp, thus opening a user<-> clinet conversation. I'm dividing this problem into parts, for now I'm trying to read the Whatsapp Web Qr Code and display it in a template. This is already happening. The problem is that the webdriver is terminated first, as soon as the image is returned to the template, then the session cannot be validated. The webdriver remains open forever, or closes before the image is sent to the template, the image needs to go to the template via return (or another way) and the webdriver remains active for a while. How to solve this concurrent task?
# views.py
from django.shortcuts import render
from django.http import HttpResponse
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
import base64
import time
from django.shortcuts import render
def read_qr_code(request):
driver = webdriver.Firefox()
# driver.implicitly_wait(30) # mantém o webdriver ativo por 2 minutos
driver.get('https://web.whatsapp.com/')
wait = WebDriverWait(driver, 10)
qr_element = wait.until(EC.presence_of_element_located((By.XPATH, '//*[#id="app"]/div/div/div[3]/div[1]/div/div/div[2]/div/canvas')))
qr_image_binary = qr_element.screenshot_as_png
qr_image_base64 = base64.b64encode(qr_image_binary).decode('utf-8')
context = {
'image_data': qr_image_base64
}
# send_qr(request, context)
# time.sleep(20) # aguarda por 2 minutos
# driver.quit() # fecha o webdriver
return render(request, 'read_qr_code.html', context)
I solved this problmes using Threds, the code is.
# views.py
from django.shortcuts import render
from django.http import HttpResponse
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
import base64
import time
from django.shortcuts import render
import threading
def quit_driver_thread():
time.sleep(40)
driver.quit()
def read_qr_code(request):
global driver
driver = webdriver.Firefox()
driver.implicitly_wait(120)
driver.get('https://web.whatsapp.com/')
wait = WebDriverWait(driver, 10)
qr_element = wait.until(EC.presence_of_element_located((By.XPATH, '//*[#id="app"]/div/div/div[3]/div[1]/div/div/div[2]/div/canvas')))
qr_image_binary = qr_element.screenshot_as_png
qr_image_base64 = base64.b64encode(qr_image_binary).decode('utf-8')
context = {
'image_data': qr_image_base64
}
thread = threading.Thread(target=quit_driver_thread)
thread.start()
return render(request, 'read_qr_code.html', context)

Testing Django Activation email with selenium / pytest. EMAIL_BACKEND="django.core.mail.backends.filebased.EmailBackend"

I'm trying to write a function that tests activation email send by selenium Firefox client.
Activation Emails are successfully written as files under "tests/test_selenium/outbox" directory, but I"m not able to handle email in test_activation_mail() method.
Django==2.2
pytest-django==3.8.0
settings.py
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = os.path.join(BASE_DIR, "tests", "test_selenium", "outbox")
test_registration.py
import pytest, time, os
from django.core import mail
from src import settings
from yaml import safe_load
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
# firefox driver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
#pytest.mark.django_db(transaction=True)
class TestCreateAccount():
t_username = "Pesho"
t_password = "alabala"
t_perm_email_1 = "pesho#example.com"
t_perm_email_2 = "pesho#example.com"
t_denied_email = "pesho#gmail.com"
def setup_method(self, method):
# Load config and check/download browser driver
config_file = 'tests/test_selenium/selenium_config.yml'
with open(config_file) as ymlfile:
cfg = safe_load(ymlfile)
# Firefox headless option
options = Options()
if cfg['HEADLESS_BROWSER']:
options.headless=True
if cfg['BROWSER'].lower() == 'firefox':
# check if driver is downloaded
try:
if os.path.isfile(cfg['SELENIUM_DRIVER_FF_BIN']):
print(f"Driver {cfg['SELENIUM_DRIVER_FF_BIN']} found")
except Exception as e:
raise(f'Driver not found: {e} run selenium_downloader.py first')
self.driver = webdriver.Firefox(
options=options,
# firefox_profile = ff_profile,
# capabilities=firefox_capabilities,
# firefox_binary=binary,
executable_path=cfg['SELENIUM_DRIVER_FF_BIN'])
elif cfg['BROWSER'].lower() == 'chrome':
raise NotImplementedError
def teardown_method(self, method):
# time.sleep(120)
self.driver.quit()
def test_activation_mail(self):
mail.outbox = []
m = mail.get_connection(backend=settings.EMAIL_BACKEND)
self.driver.get("http://127.0.0.1:8000/accounts/login/?next=/")
self.driver.set_window_size(1024, 768)
self.driver.find_element(By.LINK_TEXT, "Register").click()
self.driver.find_element(By.ID, "id_username").click()
self.driver.find_element(By.ID, "id_username").send_keys(self.t_username)
self.driver.find_element(By.ID, "id_email").send_keys(self.t_perm_email_1)
self.driver.find_element(By.ID, "id_password1").send_keys(self.t_password)
self.driver.find_element(By.ID, "id_password2").send_keys(self.t_password)
self.driver.find_element(By.ID, "id_password2").send_keys(Keys.ENTER)
alert_success = WebDriverWait(self.driver, 4).until(
EC.presence_of_element_located((By.CSS_SELECTOR, ".alert")))
if alert_success.text == f"New account created for {self.t_username}, Please check your email and confirm registration.":
# print(f'File name: {m._fname}')
email = mail.outbox[0]
assert len(mail.outbox) == 1
Running that test with:
pkill -f geckodriver ; sleep 3 ; pytest -v --ds=src.settings --pdb --pdbcls=IPython.terminal.debugger:Pdb tests/tests_selenium/test_registration.py::TestCreateAccount::test_activation_mail
Ends with Error :
E IndexError: list index out of range
because of the empty mail.outbox
What do I miss here ?

Indentation error: unident doesnt mach any outer dent level, whle executing python selenium webdriver

from Libs.Core.GetConfig import GetConfig
from Libs.Common import Logging
import os
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from HtmlTestRunner import HTMLTestRunner
import HtmlTestRunner
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
class Dummy(GetConfig):
def __init__(self, namespace=__name__, level="info"):
super(Dummy, self).__init__(namespace, level)
self._level = level
self._namespace = namespace
self._log = Logging.GetLogger(namespace, self._level)
def test_ail_login(self):
driver=self.driver
driver=webdriver.firefox()
driver.get("www.ultimatix.net")
self.username1=self.driver.find_element_by_id("USER")
self.username1.clear()
self.password1=self.driver.find_element_by_id("PASSWORD")
self.password1.clear()
#title1=self.driver.title()
#self.assertIn("Ultimatix - Digitally Connected !", driver.title,"both the names of titles are not identicle")
self.assertTrue(driver.title=="Ultimatix - Digitally Connected !" ,"both titles are not same")
assert "No results found." not in driver.page_source
self.username1.send_keys("asdfasdfasdfasdf")
self.password1.send_keys("asdfasdfasdf")
driver.find_element_by_id("login_button").click()
driver.close()
error is : at
from Libs.Core.GetConfig import GetConfig
from Libs.Common import Logging
import os
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from HtmlTestRunner import HTMLTestRunner
import HtmlTestRunner
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
class Dummy(GetConfig):
def __init__(self, namespace=__name__, level="info"):
super(Dummy, self).__init__(namespace, level)
self._level = level
self._namespace = namespace
self._log = Logging.GetLogger(namespace, self._level)
def test_tcsmail_login(self):
driver=self.driver
driver=webdriver.firefox()
driver.get("www.ultimatix.net")
self.username1=self.driver.find_element_by_id("USER")
self.username1.clear()
self.password1=self.driver.find_element_by_id("PASSWORD")
self.password1.clear()
#title1=self.driver.title()
#self.assertIn("Ultimatix - Digitally Connected !", driver.title,"both the names of titles are not identicle")
self.assertTrue(driver.title=="Ultimatix - Digitally Connected !" ,"both titles are not same")
assert "No results found." not in driver.page_source
self.username1.send_keys("dfds")
self.password1.send_keys("afdssd")
driver.find_element_by_id("login_button").click()
driver.close()

One Chrome browser window in selenium webdriver --python

I have some issue with the init constructor related to selenium webdriver's chrome instances.
Here are the pieces of my scripts:
First one named methods.py
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import paths
class PagePatterns(object):
def __init__(self, title=None):
self.driver = webdriver.Chrome('C:\Python27\chromedriver.exe')
self.title = title
def get_page_title(self):
return self.get_driver().title
Second one named login.py
from utils.methods import PagePatterns
from selenium.webdriver.common.by import By
from utils import paths
methods = PagePatterns()
class LoginPage(object):
def login(self):
country_choose = (By.XPATH, paths.country_list_login)
methods.click(country_choose)
Next one - register.py
from utils.methods import PagePatterns
from selenium.webdriver.common.by import By
from utils import utils, paths
from selenium.webdriver.support.wait import WebDriverWait
methods = PagePatterns()
class MainPage(object):
def open_homepage(self):
methods.open_base_page()
title_check = methods.get_page_title()
assert title_check == paths.page_title
The last one main_test.py is using LoginPage class
from register import MainPage
from login import LoginPage
MainPage().open_homepage()
LoginPage().login()
That's all about the code. My question is - when I am running main_test.py Chrome is called two times (two windows), but I want only one window of the browser - how to make it?
Thanks.

Flask questions about BaseConverter and __init.py__

I am trying to use a custom Baseconverter to ensure that my urls are "clean". I finally got it to work as follows:
My init.py is:
import os
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.login import LoginManager
from flask.ext.openid import OpenID
from config import basedir
from slugify import slugify
app = Flask(__name__)
from werkzeug.routing import BaseConverter
class MyStringConverter(BaseConverter):
def to_python(self, value):
return value
def to_url(self, values):
return slugify(values)
app.url_map.converters['mystring'] = MyStringConverter
app.config.from_object('config')
db = SQLAlchemy(app)
lm = LoginManager()
lm.init_app(app)
lm.login_view = 'login'
oid = OpenID(app, os.path.join(basedir, 'tmp'))
from app import views, models
But if I define the MyStringConverter class and add app.url_map.converters['mystring'] = MyStringConverter at the end of the file instead, I got a LookupError: the converter 'mystring' does not exist error. Why is this?
Is this the correct way to clean up my urls? I'm not sure if I need to do anything to the to_python() method or if I am going about this the right way.