Skip to content
Merged
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
287 changes: 287 additions & 0 deletions ci/Jenkinsfile.tests-e2e.windows
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
#!/usr/bin/env groovy
library '[email protected]'

pipeline {

agent {
label 'windows && x86_64 && qt-6.9.2 && windows-e2e'
}

parameters {
gitParameter(
name: 'GIT_REF',
description: 'Git branch to checkout.',
branchFilter: 'origin/(.*)',
branch: '',
defaultValue: 'master',
quickFilterEnabled: false,
selectedValue: 'DEFAULT',
sortMode: 'ASCENDING_SMART',
tagFilter: '*',
type: 'PT_BRANCH'
)
string(
name: 'BUILD_SOURCE',
description: 'URL to tar.gz file OR path to Jenkins build.',
defaultValue: getDefaultBuildSource()
)
string(
name: 'TEST_NAME',
description: 'Paste test name/part of test name to run specific test.',
defaultValue: ''
)
string(
name: 'TEST_SCOPE_FLAG',
description: 'Paste a known mark to run tests labeled with this mark',
defaultValue: getDefaultTestScopeFlag()
)
string(
name: 'TESTRAIL_RUN_NAME',
description: 'Test run name in Test Rail.',
defaultValue: ''
)
choice(
name: 'LOG_LEVEL',
description: 'Log level for pytest.',
choices: ['INFO', 'DEBUG', 'TRACE', 'WARNING', 'CRITICAL']
)
}

options {
timestamps()
/* Prevent Jenkins jobs from running forever */
timeout(time: 120, unit: 'MINUTES')
/* manage how many builds we keep */
buildDiscarder(logRotator(
daysToKeepStr: '60',
numToKeepStr: '50',
artifactNumToKeepStr: '50',
))
disableRestartFromStage()
}

environment {
PLATFORM = 'tests/e2e'

SQUISH_DIR = 'C:\\squish-runner-9.0.1-qt-6.9'
PYTHONPATH = "${SQUISH_DIR}\\lib;${SQUISH_DIR}\\bin;${SQUISH_DIR}\\lib\\python;${PYTHONPATH}"

/* To stop e2e tests using port 8545 */
STATUS_RUNTIME_HTTP_API = 'False'
STATUS_RUNTIME_WS_API = 'False'

/* Avoid race conditions with other builds using virtualenv. */
VIRTUAL_ENV = "${WORKSPACE_TMP}\\venv"
PATH = "${VIRTUAL_ENV}\\bin;C:\\Qt\\6.9.2\\msvc2022_64\\bin;${PATH}"

/* To store user configuratiin files in temp dir */
XDG_CONFIG_HOME = "${WORKSPACE_TMP}/config"

TESTRAIL_URL = 'https://ethstatus.testrail.net'
TESTRAIL_PROJECT_ID = 18
/* Override QT xcb plugin with linux to avoid errors like:
* "Could not load the Qt platform plugin "xcb" in "" even though it was found."
QT_QPA_PLATFORM = "linuxfb"*/

/* Runtime flag to make testing of the app easier. Switched off: unpredictable app behavior under new tests */
STATUS_RUNTIME_TEST_MODE = 1

/* Logging rules let you enable or disable logging for categories */
/* QT_LOGGING_RULES = '*.warning=true' */

/* Set to a non-zero value to make Qt print out diagnostic information about the each (C++) plugin it tries to load. */
/* QT_DEBUG_PLUGINS = 0 */

/* Hack fix for params not being set in job on first run */
BUILD_SOURCE = "${params.BUILD_SOURCE}"
TEST_NAME = "${params.TEST_NAME}"
TEST_SCOPE_FLAG = "${params.TEST_SCOPE_FLAG}"
TESTRAIL_RUN_NAME = "${params.TESTRAIL_RUN_NAME}"
LOG_LEVEL = "${params.LOG_LEVEL}"

/* Forces QT to use OpenGL for rendering instead of default Direct3D 11 */
QSG_RHI_BACKEND = 'opengl'
}

stages {
stage('Cleanup Workspace') {
steps {
sh './scripts/clean-git.sh'
}
}
stage('Prep') {
steps { script {
setNewBuildName()
updateGitHubStatus()
} }
}

stage('Deps') {
steps { script { dir('test/e2e') {
bat """
python310 -m venv ${VIRTUAL_ENV}
python310 -m pip install --upgrade pip
python310 -m pip install -r requirements.txt
"""
} } }
}

stage('Download') {
when { expression { params.BUILD_SOURCE.startsWith('http') } }
steps { timeout(5) { script { dir('test/e2e') {
sh 'mkdir -p ./pkg/'
setBuildDescFromFile(params.BUILD_SOURCE)
fileOperations([
fileDownloadOperation(
url: params.BUILD_SOURCE,
targetFileName: 'StatusIm-Desktop.7z',
targetLocation: './pkg/',
userName: '',
password: '',
)
])
} } } }
}

stage('Copy') {
when { expression { ! params.BUILD_SOURCE.startsWith('http') } }
steps { timeout(5) { script { dir('test/e2e') {
copyArtifacts(
projectName: params.BUILD_SOURCE,
filter: 'pkg/*-x86_64.7z',
selector: lastWithArtifacts(),
target: './'
)
setBuildDescFromFile(utils.findFile('pkg/*7z'))
} } } }
}

stage('Unpack') {
steps { timeout(5) { script { dir('test/e2e') {
sh 'mkdir aut'
sh "7z x '${utils.findFile('pkg/*.7z')}' -o'./aut'"
env.AUT_PATH = utils.findFile('aut/Status/bin/Status.exe').replace('\\','/')
} } } }
}

stage('Test') {
steps {
timeout(time: getTestStageTimeout()) {
dir('test/e2e') {
/* Lock the agent so we run only one e2e build at a time */
lock(resource: "e2e-windows-${env.NODE_NAME}", quantity: 1) {
script {
def flags = []
if (params.TEST_NAME) { flags.add("-k=${params.TEST_NAME}") }
if (params.TEST_SCOPE_FLAG) { flags.add(params.TEST_SCOPE_FLAG) }
if (params.LOG_LEVEL) { flags.addAll(["--log-level=${params.LOG_LEVEL}", "--log-cli-level=${params.LOG_LEVEL}"]) }
def flagStr = flags.join(' ')

withCredentials([
usernamePassword(credentialsId: 'test-rail-api-devops', usernameVariable: 'TESTRAIL_USR', passwordVariable: 'TESTRAIL_PSW'),
string(credentialsId: 'wallet-test-user-seed', variable: 'WALLET_TEST_USER_SEED')
]) {
sh"""
pushd configs
ln -sf _local.ci.py _local.py || cp _local.ci.py _local.py
popd

"""
bat"""
python310 -m pytest -m "not keycard" -v --reruns=1 --timeout=300 ${flagStr} --disable-warnings --alluredir=./allure-results -o timeout_func_only=true
"""
}
}
}
}
}
}
}
}

post {
always { script { dir('test/e2e') {
archiveArtifacts('aut/Status/bin/*.log')

/* Needed to categorize types of errors and add environment section in allure report. */
sh 'cp ext/allure_files/categories.json allure-results'
sh 'cp ext/allure_files/environment.properties allure-results'

allure([
results: [[path: 'allure-results']],
reportBuildPolicy: 'ALWAYS',
properties: [],
jdk: '',
])
/* Link for Jenkins Builds GitHub comment. */
env.PKG_URL = "${env.BUILD_URL}allure/"
updateGitHubStatus()
} } }
success { script {
github.notifyPR(true)
} }
failure { script {
github.notifyPR(false)
discord.send(
header: '**Desktop E2E test failure!**',
cred: 'discord-status-desktop-e2e-webhook',
)
} }
cleanup { cleanWs(disableDeferredWipeout: true) }
}
}

def setNewBuildName() {
if (currentBuild.upstreamBuilds) {
def parent = utils.parentOrCurrentBuild()
currentBuild.displayName = parent.getFullDisplayName().minus('status-desktop » ')
}
}

def setBuildDescFromFile(fileNameOrPath) {
def tokens = utils.parseFilename(utils.baseName(fileNameOrPath))
if (tokens == null) { /* Fallback for regex fail. */
currentBuild.description = utils.baseName(fileNameOrPath)
return
}
if (tokens.build && tokens.build.startsWith('pr')) {
currentBuild.displayName = tokens.build.replace(/^pr/, 'PR-')
}
currentBuild.description = formatMap([
Node: NODE_NAME,
Build: tokens.build,
Commit: tokens.commit,
Version: (tokens.tstamp ?: tokens.version),
])
}

def updateGitHubStatus() {
/* For PR builds update check status. */
if (params.BUILD_SOURCE ==~ /.*\/PR-[0-9]+\/?$/) {
github.statusUpdate(
context: 'jenkins/prs/tests/e2e-new.windows',
commit: jenkins.getJobCommitByPath(params.BUILD_SOURCE),
repo_url: 'https://github.com/status-im/status-desktop'
)
}
}

def formatMap(Map data=[:]) {
def text = ''
data.each { key, val -> text += "<b>${key}</b>: ${val}</a><br>\n" }
return text
}

def getDefaultBuildSource() {
return ''
}

def getDefaultTestScopeFlag() {
if (JOB_NAME == "status-desktop/systems/windows/x86_64/tests-e2e") {
return ''
} else {
return '-m=critical'
}
}

def getTestStageTimeout() { params.TEST_SCOPE_FLAG == '-m=critical' ? 30 : 120 }
17 changes: 16 additions & 1 deletion ci/Jenkinsfile.windows
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ pipeline {
QTDIR = "/c/Qt/6.9.2/msvc2022_64"
PATH = "${env.QTDIR}/bin:${goPath()}/bin:${env.PATH}"
/* Avoid weird bugs caused by stale cache. */
QML_DISABLE_DISK_CACHE = "true"
QML_DISABLE_DISK_CACHE = 1
/* Control output the filename */
VERSION = sh(script: "./scripts/version.sh", returnStdout: true).trim()
STATUS_CLIENT_EXE = "pkg/${utils.pkgFilename(ext: 'exe', arch: getArch(), version: env.VERSION)}"
Expand Down Expand Up @@ -149,6 +149,21 @@ pipeline {
jenkins.setBuildDesc(Zip: zip_url, Exe: exe_url)
} }
}


stage('E2E') {
when { expression { utils.isPRBuild() } }
steps { script {
build(
job: 'status-desktop/e2e/prs-windows',
wait: false,
parameters: jenkins.mapToParams([
GIT_REF: env.GIT_COMMIT,
BUILD_SOURCE: env.JOB_NAME,
]),
)
} }
}
}
post {
success { script { github.notifyPR(true) } }
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/configs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

if AUT_PATH is None:
exit('Please add "AUT_PATH" in ./configs/_local.py')
if get_platform() == "Windows" and 'bin' not in AUT_PATH:
exit('Please use launcher from "bin" folder in "AUT_PATH"')
if get_platform() == "Windows" and 'Status' not in AUT_PATH:
exit('Please use launcher from "Status" folder in "AUT_PATH"')
AUT_PATH = SystemPath(AUT_PATH)
WALLET_SEED = os.getenv('WALLET_TEST_USER_SEED')

Expand Down
26 changes: 26 additions & 0 deletions test/e2e/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import allure
import pytest
import shortuuid
import sys

from tests import test_data
from PIL import ImageGrab
Expand All @@ -12,6 +13,9 @@
from scripts.utils.system_path import SystemPath

# Send logs to pytest.log as well
# Ensure log directory exists
log_dir = os.path.dirname(configs.PYTEST_LOG)
os.makedirs(log_dir, exist_ok=True)
handler = logging.FileHandler(filename=configs.PYTEST_LOG)
logging.basicConfig(
level=os.getenv('LOG_LEVEL', 'INFO'),
Expand All @@ -28,9 +32,31 @@
]


@pytest.fixture(scope='session', autouse=True)
def generate_allure_environment():
"""Generate allure environment.properties with dynamic platform information"""
env_dir = configs.testpath.ROOT / 'ext' / 'allure_files'
env_file = env_dir / 'environment.properties'

# Ensure directory exists
env_dir.mkdir(parents=True, exist_ok=True)

platform_name = get_platform()
python_version = f"Python {sys.version_info.major}.{sys.version_info.minor}"

content = f"""os_platform = {platform_name}
python_version = {python_version}
"""

env_file.write_text(content)
LOG.info(f'Generated allure environment.properties with platform={platform_name}, python={python_version}')
yield


@pytest.fixture(scope='session', autouse=True)
def setup_session_scope(
# init_testrail_api, TODO: https://github.com/status-im/status-desktop/issues/18288
generate_allure_environment,
prepare_test_directory,
start_squish_server
):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from allure_commons._allure import step

import driver
from configs import get_platform
from constants.community import Channel
from gui.main_window import MainWindow
from helpers.multiple_instances_helper import (
Expand All @@ -26,6 +27,7 @@
@pytest.mark.communities
@pytest.mark.smoke
@pytest.mark.critical
@pytest.mark.skipif(get_platform() == 'Windows', reason="https://github.com/status-im/status-desktop/issues/18994")
def test_create_edit_join_community_pin_unpin_message(multiple_instances):
user_one: UserAccount = RandomUser()
user_two: UserAccount = RandomUser()
Expand Down
Loading