Merge pull request #1724 from antdanchenko/test/group-chat-#165
added group chat test and auto retrieving of latest apk from nightly builds
This commit is contained in:
commit
b1bf5a4fcd
|
@ -1,5 +1,5 @@
|
||||||
node {sauce('6269510b-13f3-4019-b156-c2c835f3a408') {
|
node {sauce('6269510b-13f3-4019-b156-c2c835f3a408') {
|
||||||
try {sh '/usr/local/bin/python3 -m pytest -m sanity -n5 --apk apkUrl --build ${JOB_NAME}__${BUILD_NUMBER}'
|
try {sh '/usr/local/bin/python3 -m pytest -m sanity -v --dist=loadscope -n3 --build ${JOB_NAME}__${BUILD_NUMBER}'
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
saucePublisher()
|
saucePublisher()
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
[pytest]
|
[pytest]
|
||||||
norecursedirs = .git views
|
norecursedirs = .git views
|
||||||
addopts = -s -v --junitxml=result.xml --tb=short
|
addopts = -s --junitxml=result.xml --tb=short
|
||||||
|
|
|
@ -1,12 +1,63 @@
|
||||||
from tests import tests_data
|
from tests import tests_data
|
||||||
import time
|
import time
|
||||||
|
import requests
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
from datetime import datetime
|
||||||
|
from os import environ
|
||||||
|
from io import BytesIO
|
||||||
|
from sauceclient import SauceClient
|
||||||
|
|
||||||
|
storage = 'http://artifacts.status.im:8081/artifactory/nightlies-local/'
|
||||||
|
|
||||||
|
sauce_username = environ.get('SAUCE_USERNAME')
|
||||||
|
sauce_access_key = environ.get('SAUCE_ACCESS_KEY')
|
||||||
|
|
||||||
|
|
||||||
|
def get_latest_apk():
|
||||||
|
raw_data = requests.request('GET', storage).text
|
||||||
|
dates = re.findall("\d{2}-[a-zA-Z]{3}-\d{4} \d{2}:\d{2}", raw_data)
|
||||||
|
dates.sort(key=lambda date: datetime.strptime(date, "%d-%b-%Y %H:%M"), reverse=True)
|
||||||
|
return re.findall('>(.*k)</a>\s*%s' % dates[0], raw_data)[0]
|
||||||
|
|
||||||
|
latest_apk = get_latest_apk()
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
parser.addoption("--build", action="store", default='build_' + time.strftime('%Y_%m_%d_%H_%M'),
|
parser.addoption("--build",
|
||||||
|
action="store",
|
||||||
|
default='build_' + time.strftime('%Y_%m_%d_%H_%M'),
|
||||||
help="Specify build name")
|
help="Specify build name")
|
||||||
parser.addoption('--apk', action='store', default=None, help='Please provide url or local path to apk')
|
parser.addoption('--apk',
|
||||||
|
action='store',
|
||||||
|
default='sauce-storage:' + latest_apk,
|
||||||
|
help='Please provide url or local path to apk')
|
||||||
|
|
||||||
|
|
||||||
def pytest_runtest_setup(item):
|
def pytest_runtest_setup(item):
|
||||||
tests_data.name = item.name
|
tests_data.name = item.name + '_' + latest_apk
|
||||||
|
|
||||||
|
|
||||||
|
def is_master(config):
|
||||||
|
return not hasattr(config, 'slaveinput')
|
||||||
|
|
||||||
|
|
||||||
|
def is_uploaded():
|
||||||
|
stored_files = SauceClient(sauce_username, sauce_access_key).storage.get_stored_files()
|
||||||
|
for i in range(len(stored_files['files'])):
|
||||||
|
if stored_files['files'][i]['name'] == latest_apk:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_configure(config):
|
||||||
|
if is_master(config):
|
||||||
|
if not is_uploaded():
|
||||||
|
response = requests.get(storage + latest_apk, stream=True)
|
||||||
|
response.raise_for_status()
|
||||||
|
file = BytesIO(response.content)
|
||||||
|
del response
|
||||||
|
requests.post('http://saucelabs.com/rest/v1/storage/'
|
||||||
|
+ sauce_username + '/' + latest_apk + '?overwrite=true',
|
||||||
|
auth=(sauce_username, sauce_access_key),
|
||||||
|
data=file,
|
||||||
|
headers={'Content-Type': 'application/octet-stream'})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
|
|
||||||
def set_chat_for_users_from_scratch(*args):
|
def set_password_as_new_user(*args):
|
||||||
for view in args:
|
for view in args:
|
||||||
view.request_password_icon.click()
|
view.request_password_icon.click()
|
||||||
view.type_message_edit_box.send_keys("qwerty1234")
|
view.type_message_edit_box.send_keys("qwerty1234")
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import pytest
|
import pytest
|
||||||
from tests.basetestcase import MultiplyDeviceTestCase
|
from tests.basetestcase import MultiplyDeviceTestCase
|
||||||
from tests.preconditions import set_chat_for_users_from_scratch
|
from tests.preconditions import set_password_as_new_user
|
||||||
from views.home import HomeView
|
from views.home import HomeView
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sanity
|
@pytest.mark.sanity
|
||||||
class TestMultiplyDevices(MultiplyDeviceTestCase):
|
class TestChats(MultiplyDeviceTestCase):
|
||||||
|
|
||||||
def test_private_chat(self):
|
def test_private_chat(self):
|
||||||
|
|
||||||
device_1, device_2 = HomeView(self.driver_1), HomeView(self.driver_2)
|
device_1, device_2 = HomeView(self.driver_1), HomeView(self.driver_2)
|
||||||
set_chat_for_users_from_scratch(device_1, device_2)
|
set_password_as_new_user(device_1, device_2)
|
||||||
|
|
||||||
device_1.back_button.click()
|
device_1.back_button.click()
|
||||||
chats_d1 = device_1.get_chats()
|
chats_d1 = device_1.get_chats()
|
||||||
chats_d1.profile_button.click()
|
chats_d1.profile_button.click()
|
||||||
profile_d1 = chats_d1.profile_icon.click()
|
profile_d1 = chats_d1.profile_icon.click()
|
||||||
key = profile_d1.public_key_text.get_key()
|
key = profile_d1.public_key_text.text
|
||||||
|
|
||||||
device_2.back_button.click()
|
device_2.back_button.click()
|
||||||
chats_d2 = device_2.get_chats()
|
chats_d2 = device_2.get_chats()
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
import pytest
|
||||||
|
from tests.basetestcase import MultiplyDeviceTestCase
|
||||||
|
from tests.preconditions import set_password_as_new_user
|
||||||
|
from views.home import HomeView
|
||||||
|
from views.chats import UserNameText
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sanity
|
||||||
|
class TestDev(MultiplyDeviceTestCase):
|
||||||
|
|
||||||
|
def test_group_chat(self):
|
||||||
|
device_1, device_2 = HomeView(self.driver_1), \
|
||||||
|
HomeView(self.driver_2)
|
||||||
|
|
||||||
|
set_password_as_new_user(device_2, device_1)
|
||||||
|
|
||||||
|
device_1.back_button.click()
|
||||||
|
chats_d1 = device_1.get_chats()
|
||||||
|
chats_d1.profile_button.click()
|
||||||
|
profile_d1 = chats_d1.profile_icon.click()
|
||||||
|
key = profile_d1.public_key_text.text
|
||||||
|
|
||||||
|
device_2.back_button.click()
|
||||||
|
chats_d2 = device_2.get_chats()
|
||||||
|
chats_d2.plus_button.click()
|
||||||
|
chats_d2.add_new_contact.click()
|
||||||
|
chats_d2.public_key_edit_box.send_keys(key)
|
||||||
|
chats_d2.confirm()
|
||||||
|
chats_d2.confirm_public_key_button.click()
|
||||||
|
|
||||||
|
user_d1_name = chats_d2.user_name_text.text
|
||||||
|
|
||||||
|
device_2.back_button.click()
|
||||||
|
chats_d2.new_group_chat_button.click()
|
||||||
|
|
||||||
|
profile_d1.back_button.click()
|
||||||
|
|
||||||
|
user_contact = UserNameText.UserContactByName(self.driver_2, user_d1_name)
|
||||||
|
user_contact.scroll_to_element()
|
||||||
|
user_contact.click()
|
||||||
|
|
||||||
|
chats_d2.next_button.click()
|
||||||
|
chats_d2.name_edit_box.send_keys('new_chat')
|
||||||
|
chats_d2.save_button.click()
|
||||||
|
|
||||||
|
chats_d2.chat_message_input.send_keys('SOMETHING')
|
||||||
|
chats_d2.send_message_button.click()
|
||||||
|
|
||||||
|
profile_d1.find_text('SOMETHING')
|
|
@ -2,6 +2,7 @@ from selenium.webdriver.common.by import By
|
||||||
from selenium.common.exceptions import NoSuchElementException, TimeoutException
|
from selenium.common.exceptions import NoSuchElementException, TimeoutException
|
||||||
from selenium.webdriver.support.wait import WebDriverWait
|
from selenium.webdriver.support.wait import WebDriverWait
|
||||||
from selenium.webdriver.support import expected_conditions
|
from selenium.webdriver.support import expected_conditions
|
||||||
|
from appium.webdriver.common.touch_action import TouchAction
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,16 +33,22 @@ class BaseElement(object):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def find_element(self):
|
def find_element(self):
|
||||||
try:
|
return self.driver.find_element(self.locator.by, self.locator.value)
|
||||||
return self.wait_for_element()
|
|
||||||
except (NoSuchElementException, TimeoutException):
|
|
||||||
pytest.fail("'%s' not found by %s '%s'" % (
|
|
||||||
self.name, self.locator.by, self.locator.value), pytrace=False)
|
|
||||||
|
|
||||||
def wait_for_element(self, seconds=30):
|
def wait_for_element(self, seconds=10):
|
||||||
return WebDriverWait(self.driver, seconds)\
|
return WebDriverWait(self.driver, seconds)\
|
||||||
.until(expected_conditions.presence_of_element_located((self.locator.by, self.locator.value)))
|
.until(expected_conditions.presence_of_element_located((self.locator.by, self.locator.value)))
|
||||||
|
|
||||||
|
def scroll_to_element(self):
|
||||||
|
for x in range(10):
|
||||||
|
action = TouchAction(self.driver)
|
||||||
|
action.press(x=0, y=1000).move_to(x=200, y=-1000).release().perform()
|
||||||
|
try:
|
||||||
|
self.find_element()
|
||||||
|
break
|
||||||
|
except NoSuchElementException:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BaseEditBox(BaseElement):
|
class BaseEditBox(BaseElement):
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,9 @@ class BaseViewObject(object):
|
||||||
self.driver.keyevent(66)
|
self.driver.keyevent(66)
|
||||||
|
|
||||||
def find_text(self, text):
|
def find_text(self, text):
|
||||||
element = BaseElement(self.driver)
|
element = BaseButton(self.driver)
|
||||||
element.locator = element.Locator.xpath_selector('//*[@text="' + text + '"]')
|
element.locator = element.Locator.xpath_selector('//*[@text="' + text + '"]')
|
||||||
return element.wait_for_element(30)
|
return element.wait_for_element(100)
|
||||||
|
|
||||||
def get_chats(self):
|
def get_chats(self):
|
||||||
from views.chats import ChatsViewObject
|
from views.chats import ChatsViewObject
|
||||||
|
|
|
@ -7,7 +7,8 @@ class ProfileButton(BaseButton):
|
||||||
def __init__(self, driver):
|
def __init__(self, driver):
|
||||||
super(ProfileButton, self).__init__(driver)
|
super(ProfileButton, self).__init__(driver)
|
||||||
self.locator = self.Locator.xpath_selector(
|
self.locator = self.Locator.xpath_selector(
|
||||||
"//android.support.v4.view.ViewPager//android.view.ViewGroup[1]/android.widget.ImageView")
|
"//android.support.v4.view.ViewPager//android.view.ViewGroup[2]/android.view.ViewGroup[1]/android.view.View"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ProfileIcon(BaseButton):
|
class ProfileIcon(BaseButton):
|
||||||
|
@ -38,6 +39,44 @@ class AddNewContactButton(BaseButton):
|
||||||
"//android.widget.TextView[@text='Add new contact']")
|
"//android.widget.TextView[@text='Add new contact']")
|
||||||
|
|
||||||
|
|
||||||
|
class NewGroupChatButton(BaseButton):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(NewGroupChatButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector(
|
||||||
|
"//android.widget.TextView[@text='New group chat']")
|
||||||
|
|
||||||
|
class AugurContact(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(NewGroupChatButton.AugurContact, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector(
|
||||||
|
"//android.widget.TextView[@text='Augur']")
|
||||||
|
|
||||||
|
class JarradContact(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(NewGroupChatButton.JarradContact, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector(
|
||||||
|
"//android.widget.TextView[@text='Jarrad']")
|
||||||
|
|
||||||
|
class NextButton(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(NewGroupChatButton.NextButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector(
|
||||||
|
"//android.widget.TextView[@text='NEXT']")
|
||||||
|
|
||||||
|
class NameEditBox(BaseEditBox):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(NewGroupChatButton.NameEditBox, self).__init__(driver)
|
||||||
|
self.locator = \
|
||||||
|
self.Locator.xpath_selector("//android.widget.EditText[@NAF='true']")
|
||||||
|
|
||||||
|
class SaveButton(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(NewGroupChatButton.SaveButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector(
|
||||||
|
"//android.widget.TextView[@text='SAVE']")
|
||||||
|
|
||||||
|
|
||||||
class PublicKeyEditBox(BaseEditBox):
|
class PublicKeyEditBox(BaseEditBox):
|
||||||
|
|
||||||
def __init__(self, driver):
|
def __init__(self, driver):
|
||||||
|
@ -73,6 +112,20 @@ class SendMessageButton(BaseButton):
|
||||||
"android.view.ViewGroup[2]//android.widget.ImageView")
|
"android.view.ViewGroup[2]//android.widget.ImageView")
|
||||||
|
|
||||||
|
|
||||||
|
class UserNameText(BaseText):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(UserNameText, self).__init__(driver)
|
||||||
|
self.locator = \
|
||||||
|
self.Locator.xpath_selector("//android.widget.ScrollView//android.widget.TextView")
|
||||||
|
|
||||||
|
class UserContactByName(BaseButton):
|
||||||
|
|
||||||
|
def __init__(self, driver, user_name):
|
||||||
|
super(UserNameText.UserContactByName, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector('//*[@text="' + user_name + '"]')
|
||||||
|
|
||||||
|
|
||||||
class ChatsViewObject(BaseViewObject):
|
class ChatsViewObject(BaseViewObject):
|
||||||
|
|
||||||
def __init__(self, driver):
|
def __init__(self, driver):
|
||||||
|
@ -83,7 +136,17 @@ class ChatsViewObject(BaseViewObject):
|
||||||
self.profile_icon = ProfileIcon(self.driver)
|
self.profile_icon = ProfileIcon(self.driver)
|
||||||
self.plus_button = PlusButton(self.driver)
|
self.plus_button = PlusButton(self.driver)
|
||||||
self.add_new_contact = AddNewContactButton(self.driver)
|
self.add_new_contact = AddNewContactButton(self.driver)
|
||||||
|
|
||||||
self.public_key_edit_box = PublicKeyEditBox(self.driver)
|
self.public_key_edit_box = PublicKeyEditBox(self.driver)
|
||||||
self.confirm_public_key_button = ConfirmPublicKeyButton(self.driver)
|
self.confirm_public_key_button = ConfirmPublicKeyButton(self.driver)
|
||||||
|
|
||||||
self.chat_message_input = ChatMessageInput(self.driver)
|
self.chat_message_input = ChatMessageInput(self.driver)
|
||||||
self.send_message_button = SendMessageButton(self.driver)
|
self.send_message_button = SendMessageButton(self.driver)
|
||||||
|
self.user_name_text = UserNameText(self.driver)
|
||||||
|
|
||||||
|
self.new_group_chat_button = NewGroupChatButton(self.driver)
|
||||||
|
self.augur_contact = NewGroupChatButton.AugurContact(self.driver)
|
||||||
|
self.jarrad_contact = NewGroupChatButton.JarradContact(self.driver)
|
||||||
|
self.next_button = NewGroupChatButton.NextButton(self.driver)
|
||||||
|
self.name_edit_box = NewGroupChatButton.NameEditBox(self.driver)
|
||||||
|
self.save_button = NewGroupChatButton.SaveButton(self.driver)
|
||||||
|
|
|
@ -9,6 +9,13 @@ class ContinueButton(BaseButton):
|
||||||
self.locator = self.Locator.xpath_selector("//*[@text='Continue']")
|
self.locator = self.Locator.xpath_selector("//*[@text='Continue']")
|
||||||
|
|
||||||
|
|
||||||
|
class OkButton(BaseButton):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(OkButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector("//*[@text='OK']")
|
||||||
|
|
||||||
|
|
||||||
class TypeMessageEditBox(BaseEditBox):
|
class TypeMessageEditBox(BaseEditBox):
|
||||||
|
|
||||||
def __init__(self, driver):
|
def __init__(self, driver):
|
||||||
|
@ -29,11 +36,13 @@ class HomeView(BaseViewObject):
|
||||||
def __init__(self, driver):
|
def __init__(self, driver):
|
||||||
super(HomeView, self).__init__(driver)
|
super(HomeView, self).__init__(driver)
|
||||||
self.continue_button = ContinueButton(driver)
|
self.continue_button = ContinueButton(driver)
|
||||||
|
self.ok_button = OkButton(driver)
|
||||||
|
|
||||||
try:
|
for i in self.ok_button, self.continue_button:
|
||||||
self.continue_button.click()
|
try:
|
||||||
except Exception:
|
i.click()
|
||||||
pass
|
except (NoSuchElementException, TimeoutException):
|
||||||
|
pass
|
||||||
|
|
||||||
self.type_message_edit_box = TypeMessageEditBox(driver)
|
self.type_message_edit_box = TypeMessageEditBox(driver)
|
||||||
self.request_password_icon = RequestPasswordIcon(driver)
|
self.request_password_icon = RequestPasswordIcon(driver)
|
||||||
|
|
|
@ -6,14 +6,7 @@ class PublicKeyText(BaseText):
|
||||||
|
|
||||||
def __init__(self, driver):
|
def __init__(self, driver):
|
||||||
super(PublicKeyText, self).__init__(driver)
|
super(PublicKeyText, self).__init__(driver)
|
||||||
self.locator = self.Locator.xpath_selector("//android.widget.TextView")
|
self.locator = self.Locator.xpath_selector("//android.widget.TextView[@instance='7']")
|
||||||
|
|
||||||
def get_key(self):
|
|
||||||
texts = self.driver.find_elements(self.locator.by, self.locator.value)
|
|
||||||
for i in texts:
|
|
||||||
if i.text.startswith('0x04'):
|
|
||||||
return i.text
|
|
||||||
pytest.fail("Public key wasn't found!")
|
|
||||||
|
|
||||||
|
|
||||||
class ProfileViewObject(BaseViewObject):
|
class ProfileViewObject(BaseViewObject):
|
||||||
|
|
Loading…
Reference in New Issue