Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: new onboarding tests changes #17113

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion ci/Jenkinsfile.tests-e2e
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ pipeline {
PYTHONPATH = "${SQUISH_DIR}/lib:${SQUISH_DIR}/lib/python:${PYTHONPATH}"
LD_LIBRARY_PATH = "${SQUISH_DIR}/lib:${SQUISH_DIR}/python3/lib:${LD_LIBRARY_PATH}"

FLAG_ONBOARDING_V2_ENABLED = "true"

/* To stop e2e tests using port 8545 */
STATUS_RUNTIME_HTTP_API = 'False'
STATUS_RUNTIME_WS_API = 'False'
Expand Down Expand Up @@ -172,7 +174,7 @@ pipeline {
]) {
/* Keep the --reruns flag first, or it won't work */
sh """
python3 -m pytest -m "not keycard" -v --reruns=1 --timeout=240 ${flags.join(" ")} \
python3 -m pytest -m "not keycard" -v --timeout=240 ${flags.join(" ")} \
--disable-warnings \
--alluredir=./allure-results \
-o timeout_func_only=true
Expand Down
4 changes: 1 addition & 3 deletions test/e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
1. **MacOS**: https://www.notion.so/Mac-arch-x64-and-Intel-50ea48dae1d4481b882afdbfad38e95a
2. **Linux**: https://www.notion.so/Linux-21f7abd2bb684a0fb10057848760a889
3. **Windows**: https://www.notion.so/Windows-fbccd2b09b784b32ba4174233d83878d

**NOTE:** when MacOS and Linux are proven to be working, Windows guide could be outdated (no one yet set up Windows)

## Which build to use

Expand Down Expand Up @@ -45,7 +43,7 @@ expected to fail in report with a reference to the ticket. At the same time, if
it will be shown as XPASS (unexpectedly passing) in report, which will indicate the initial bug is gone
- `skip`, used to just skip tests for various reasons, normally with a ticket linked
- `flaky`, used to mark the tests that are normally passing but sometimes fail. If such test passes, then
if will be shown as passed in report normally. If the test fails, then the total run wont be failed, but
if will be shown as passed in report normally. If the test fails, then the total run won't be failed, but
the corresponding test will be marked as `xfail` in the report. It is done for a few tests that are not super
stable yet, but passes most of the time. This mark should be used with caution and in case of real need only.
- `timeout(timeout=180, method="thread")`, to catch excessively long test durations like deadlocked or hanging tests.
Expand Down
1 change: 0 additions & 1 deletion test/e2e/configs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import logging
import os

from os import path
from scripts.utils.system_path import SystemPath
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/configs/timeouts.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Timoeuts before raising errors
# Timeouts before raising errors

UI_LOAD_TIMEOUT_SEC = 5
UI_LOAD_TIMEOUT_MSEC = UI_LOAD_TIMEOUT_SEC * 1000
Expand Down
3 changes: 0 additions & 3 deletions test/e2e/constants/user.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import random
import string
from collections import namedtuple
from dataclasses import dataclass, field
from typing import Optional

import configs
from constants import ColorCodes
from scripts.tools.image import Image
from scripts.utils.generators import random_name_string, random_password_string, random_community_name, \
random_community_description, random_community_introduction, random_community_leave_message, random_community_tags, \
Expand Down
54 changes: 32 additions & 22 deletions test/e2e/driver/aut.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import os
import time

import allure
Expand Down Expand Up @@ -48,28 +47,39 @@ def __enter__(self):

def __exit__(self, exc_type, exc_value, traceback):
if exc_type:
try:
self.attach()
driver.waitForObjectExists(statusDesktop_mainWindow).setVisible(True)
configs.testpath.TEST.mkdir(parents=True, exist_ok=True)
screenshot = configs.testpath.TEST / f'{self.aut_id}.png'

rect = driver.object.globalBounds(driver.waitForObject(statusDesktop_mainWindow))
img = ImageGrab.grab(
bbox=(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height),
xdisplay=configs.system.DISPLAY if get_platform() == "Linux" else None)
view = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)
cv2.imwrite(str(screenshot), view)

allure.attach(
name=f'Screenshot on fail: {self.aut_id}',
body=screenshot.read_bytes(),
attachment_type=allure.attachment_type.PNG)
except Exception as err:
LOG.error(err)

self._capture_screenshot()
self.stop()

def _capture_screenshot(self):
"""Captures a screenshot of the main application window if it is still running."""
try:
if driver.isRunning(self.aut_id): # Проверяем, работает ли приложение
main_window = driver.waitForObjectExists(statusDesktop_mainWindow, 500)
if main_window:
rect = driver.object.globalBounds(main_window)
screenshot = configs.testpath.TEST / f'{self.aut_id}.png'
configs.testpath.TEST.mkdir(parents=True, exist_ok=True)

img = ImageGrab.grab(
bbox=(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height),
xdisplay=configs.system.DISPLAY if get_platform() == "Linux" else None
)
view = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)
cv2.imwrite(str(screenshot), view)

allure.attach(
name=f'Screenshot on fail: {self.aut_id}',
body=screenshot.read_bytes(),
attachment_type=allure.attachment_type.PNG
)
LOG.info(f"Screenshot saved at {screenshot}")
else:
LOG.warning("Main window not found; skipping screenshot.")
else:
LOG.warning("Application is no longer running; skipping screenshot.")
except Exception as err:
LOG.error(f"Failed to capture screenshot: {err}")

def detach_context(self):
if self.ctx is None:
return
Expand Down Expand Up @@ -121,8 +131,8 @@ def startaut(self):
def stop(self):
LOG.info('Stopping AUT: %s', self.path)
self.detach_context()
time.sleep(2) # some time before kiling process, to allow screenshot capturing
local_system.kill_process(self.pid)
time.sleep(1) # FIXME: Implement waiting for process to actually exit.

@allure.step("Start and attach AUT")
def launch(self) -> 'AUT':
Expand Down
2 changes: 0 additions & 2 deletions test/e2e/fixtures/aut.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
import pytest
import logging
import constants
from configs import get_platform
from constants.user import *
from driver.aut import AUT
from gui.main_window import MainWindow
from scripts.utils import system_path
from scripts.utils.local_system import get_pid_by_process_name, kill_process
from scripts.utils.system_path import SystemPath

LOG = logging.getLogger(__name__)
Expand Down
1 change: 0 additions & 1 deletion test/e2e/fixtures/squish.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import allure
import pytest
import logging

Expand Down
8 changes: 3 additions & 5 deletions test/e2e/gui/components/activity_center.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,12 @@ def click_activity_center_button(self, text: str):
def find_contact_request_in_list(
self, contact: str, timeout_sec: int = configs.timeouts.MESSAGING_TIMEOUT_SEC):
started_at = time.monotonic()
request = None
while request is None:
while time.monotonic() - started_at < timeout_sec:
requests = self.contact_items
for _request in requests:
if _request.contact_request == contact:
request = _request
assert time.monotonic() - started_at < timeout_sec, f'Contact: {contact} not found in {requests}'
return request
return _request
raise TimeoutError(f'Timed out after {timeout_sec} seconds: Contact request "{contact}" not found.')

@allure.step('Accept contact request')
def accept_contact_request(self, request):
Expand Down
2 changes: 0 additions & 2 deletions test/e2e/gui/components/change_password_popup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import allure

import driver
from constants.settings import PasswordView
from gui.components.base_popup import BasePopup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from gui.elements.check_box import CheckBox
from gui.elements.text_edit import TextEdit
from gui.objects_map import names
from gui.screens.community_settings import PermissionsSettingsView


class ChannelPopup(BasePopup):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import allure

from gui.components.base_popup import BasePopup
from gui.elements.button import Button
from gui.objects_map import communities_names
Expand Down
4 changes: 0 additions & 4 deletions test/e2e/gui/components/community/new_permission_popup.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import allure

import configs
import driver
from driver.objects_access import walk_children
from gui.elements.button import Button
from gui.elements.check_box import CheckBox
from gui.elements.object import QObject
Expand Down
1 change: 0 additions & 1 deletion test/e2e/gui/components/community/tags_select_popup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from gui.components.base_popup import BasePopup
from gui.elements.button import Button
from gui.elements.object import QObject
from gui.elements.text_edit import TextEdit
from gui.objects_map import names


Expand Down
2 changes: 1 addition & 1 deletion test/e2e/gui/components/context_menu.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import allure

from gui.components.community.community_category_popup import CategoryPopup, EditCategoryPopup
from gui.components.community.community_category_popup import EditCategoryPopup
from gui.components.community.invite_contacts import InviteContactsPopup
from gui.components.community.leave_community_confirmation import LeaveCommunityConfirmationPopup
from gui.components.delete_popup import DeleteCategoryPopup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import configs
from gui.components.base_popup import BasePopup
from gui.elements.button import Button
from gui.elements.object import QObject
from gui.objects_map import names

Expand Down
1 change: 0 additions & 1 deletion test/e2e/gui/components/onboarding/beta_consent_popup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import allure

from gui.components.base_popup import BasePopup
from gui.elements.button import Button
from gui.elements.check_box import CheckBox
from gui.elements.object import QObject
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from gui.components.base_popup import BasePopup
from gui.elements.button import Button
from gui.objects_map import onboarding_names
from gui.elements.check_box import CheckBox


class LogInBySyncingChecklist(BasePopup):
def __init__(self):
super().__init__()
self.connect_both_devices_option = CheckBox(onboarding_names.connectBothDevicesOption)
self.make_sure_you_are_logged_option = CheckBox(onboarding_names.makeSureYouAreLoggedOption)
self.disable_the_firewall_option = CheckBox(onboarding_names.disableTheFirewallOption)
self.cancel_button = Button(onboarding_names.cancelButton)
self.continue_button = Button(onboarding_names.continueButton)

def complete(self):
self.connect_both_devices_option.set(True)
self.make_sure_you_are_logged_option.set(True)
self.disable_the_firewall_option.set(True)
assert self.continue_button.is_enabled
self.continue_button.click()
28 changes: 28 additions & 0 deletions test/e2e/gui/components/onboarding/login_users_list_popup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import driver
from gui.components.base_popup import BasePopup
from gui.elements.button import Button
from gui.elements.object import QObject
from gui.objects_map import onboarding_names


class OnboardingLoginUsersPopup(BasePopup):
def __init__(self):
super().__init__()
self.user_login_item = QObject(onboarding_names.userLoginItem)
self.create_profile_button = Button(onboarding_names.createProfileButton)
self.login_button = Button(onboarding_names.returningLoginButton)

def select_user_by_name(self, user_name):
raw_data = driver.findAllObjects(self.user_login_item.real_name)
if not raw_data:
raise ValueError(f"Can't find {user_name} in list of users as the list is empty")
for _user in raw_data:
name_label = str(QObject(_user).object.label)
if name_label == user_name:
try:
QObject(_user).click()
return self
except RuntimeError as e:
raise RuntimeError(f'Could not click user with user name "{user_name}": {e}')
else:
raise ValueError(f'User "{user_name}" was not found')
23 changes: 13 additions & 10 deletions test/e2e/gui/components/onboarding/share_usage_data_popup.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import allure

from gui.components.base_popup import BasePopup
from gui.elements.button import Button
from gui.elements.object import QObject
from gui.objects_map import names
from gui.objects_map import names, onboarding_names


class ShareUsageDataPopup(QObject):
# this is old modal shown on relogin
class ShareUsageDataPopup(BasePopup):

def __init__(self):
super().__init__(names.share_usage_data_StatusButton)
self._not_now_button = Button(names.not_now_StatusButton )
self._share_usage_data_button = Button(names.share_usage_data_StatusButton)
super().__init__()
self.not_now_button = Button(names.not_now_StatusButton)
self.share_usage_data_button = Button(names.share_usage_data_StatusButton)


@allure.step('Click not now button')
def skip(self):
self._not_now_button.click()
# this is new modal shown for initial onboarding
class HelpUsImproveStatusView(QObject):
def __init__(self):
super().__init__(onboarding_names.helpUsImproveStatusPage)
self.share_usage_data_button = Button(onboarding_names.shareUsageDataButton)
self.not_now_button = Button(onboarding_names.notNowButton)
3 changes: 0 additions & 3 deletions test/e2e/gui/components/online_identifier.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import time

import allure
import pyperclip

import configs
import constants
import driver
from gui.components.profile_popup import ProfilePopup
from gui.elements.button import Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def __init__(self):
self._copy_button = Button(names.copy_SyncCodeStatusButton)
self._done_button = Button(names.done_SyncCodeStatusButton)
self._sync_code_field = TextEdit(names.syncCodeInput_StatusPasswordInput)
self._close_button = Button(names.close_StatusButton)
self._close_button = Button(names.close_SyncCodeStatusFlatRoundButton)
self._error_message = QObject(names.errorView_SyncingErrorMessage)

@property
Expand Down
1 change: 0 additions & 1 deletion test/e2e/gui/components/share_profile_popup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import allure

import configs
import driver
from gui.components.base_popup import BasePopup
from gui.elements.button import Button
from gui.elements.object import QObject
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/gui/components/signing_phrase_popup.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import allure

from gui.components.base_popup import BasePopup
from gui.elements.button import Button
from gui.elements.object import QObject
from gui.objects_map import names


class SigningPhrasePopup(QObject):
class SigningPhrasePopup(BasePopup):

def __init__(self):
super().__init__(names.signPhrase_Ok_Button)
super().__init__()
self.ok_got_it_button = Button(names.signPhrase_Ok_Button)

@allure.step('Confirm signing phrase in popup')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import time


import allure

import configs
import driver
from gui.components.base_popup import BasePopup
from gui.components.wallet.send_popup import SendPopup
from gui.elements.object import QObject
Expand Down
1 change: 0 additions & 1 deletion test/e2e/gui/components/wallet/bridge_popup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import configs.timeouts
from gui.components.base_popup import BasePopup
from gui.elements.button import Button
from gui.elements.object import QObject
from gui.objects_map import names

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import allure

import configs
from gui.components.base_popup import BasePopup
from gui.elements.button import Button
from gui.elements.check_box import CheckBox
from gui.elements.text_label import TextLabel
from gui.objects_map import names
from gui.screens.settings_wallet import *
from gui.elements.object import QObject
from gui.elements.button import Button
from gui.elements.text_label import TextLabel
from gui.elements.check_box import CheckBox


class RemoveAccountConfirmationSettings(BasePopup):
Expand Down
Loading