Skip to content

Commit

Permalink
Merge pull request #1687 from mhsmith/test-app
Browse files Browse the repository at this point in the history
Test app
  • Loading branch information
freakboy3742 authored Dec 7, 2022
2 parents 26bfdf0 + 30295c1 commit 1971d06
Show file tree
Hide file tree
Showing 65 changed files with 804 additions and 13 deletions.
63 changes: 55 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,21 +96,13 @@ jobs:
run: |
tox -e py-core
cd core
python -m coverage xml
mv .coverage .coverage.${{ matrix.platform }}.${{ matrix.python-version }}
- name: Store coverage data
uses: actions/upload-artifact@v3
with:
name: core-coverage-data
path: "core/.coverage.*"
if-no-files-found: error
- name: Upload coverage data to CodeCov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: core/coverage.xml
flags: unittests
fail_ci_if_error: true

core-coverage:
name: Combine & check core coverage.
Expand Down Expand Up @@ -190,3 +182,58 @@ jobs:
TOGA_INSTALL_COMMAND: 'bash -c "pip install ../{core,dummy,${{ matrix.backend }}}/dist/*.whl"'
run: |
tox -e py-${{ matrix.backend }}
testbed:
needs: core
strategy:
fail-fast: false
matrix:
backend: ["macOS", "windows", "linux", "android", "iOS"]
include:
- pre-command:
briefcase-run-prefix:
briefcase-run-args:

- backend: macOS
runs-on: macos-12

- backend: linux
runs-on: ubuntu-latest
pre-command: "sudo apt-get update -y && sudo apt-get install -y python3-gi python3-gi-cairo gir1.2-gtk-3.0 python3-dev libgirepository1.0-dev libcairo2-dev pkg-config"
briefcase-run-prefix: 'xvfb-run -a -s "-screen 0 2048x1536x24"'

- backend: windows
runs-on: windows-latest

- backend: iOS
runs-on: macos-12
briefcase-run-args: ' -d "iPhone SE (3rd generation)"'

- backend: android
runs-on: macos-12
briefcase-run-args: " -d '{\"avd\":\"beePhone\"}' --Xemulator=-no-window --Xemulator=-no-snapshot --Xemulator=-no-audio --Xemulator=-no-boot-anim --shutdown-on-exit"

runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/[email protected]
with:
fetch-depth: 0
- name: Set up Python
uses: actions/[email protected]
with:
python-version: "3.X"
- name: Install dependencies
run: |
${{ matrix.pre-command }}
# Use the development version of Briefcase
pip install git+https://github.com/beeware/briefcase.git
- name: Test App
run: |
cd testbed
${{ matrix.briefcase-run-prefix }} briefcase run ${{ matrix.backend }} --test ${{ matrix.briefcase-run-args }}
- uses: actions/upload-artifact@v3
name: Upload logs
if: failure()
with:
name: testbed-failure-logs-${{ matrix.backend }}
path: testbed/logs/*
1 change: 1 addition & 0 deletions android/MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ include LICENSE
include README.rst
include tox.ini
recursive-include tests *.py
recursive-include tests_backend *.py
Empty file.
Empty file.
43 changes: 43 additions & 0 deletions android/tests_backend/widgets/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from pytest import skip


class SimpleProbe:
def __init__(self, widget):
self.native = widget._impl.native
assert isinstance(self.native, self.native_class)

def assert_container(self, container):
container_native = container._impl.native
for i in range(container_native.getChildCount()):
child = container_native.getChildAt(i)
if child is self.native:
break
else:
raise AssertionError(f"cannot find {self.native} in {container_native}")

@property
def enabled(self):
return self.native.isEnabled()

@property
def background_color(self):
skip("not implemented: background_color")

@property
def color(self):
skip("not implemented: color")

@property
def hidden(self):
skip("not implemented: hidden")

@property
def width(self):
return self.native.getWidth()

@property
def height(self):
return self.native.getHeight()

def press(self):
self.native.performClick()
8 changes: 8 additions & 0 deletions android/tests_backend/widgets/button.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from java import jclass

from .label import LabelProbe


# On Android, a Button is just a TextView with a state-dependent background image.
class ButtonProbe(LabelProbe):
native_class = jclass("android.widget.Button")
16 changes: 16 additions & 0 deletions android/tests_backend/widgets/label.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from java import jclass

from .base import SimpleProbe
from .properties import toga_color


class LabelProbe(SimpleProbe):
native_class = jclass("android.widget.TextView")

@property
def color(self):
return toga_color(self.native.getCurrentTextColor())

@property
def text(self):
return str(self.native.getText())
15 changes: 15 additions & 0 deletions android/tests_backend/widgets/properties.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from java import jint

from android.graphics import Color
from toga.colors import rgba


def toga_color(color_int):
# Select the `int` overloads rather than the `long` ones.
color_int = jint(color_int)
return rgba(
Color.red(color_int),
Color.green(color_int),
Color.blue(color_int),
Color.alpha(color_int) / 255,
)
24 changes: 24 additions & 0 deletions android/tests_backend/widgets/slider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from java import jclass

from android.os import Build

from .base import SimpleProbe


class SliderProbe(SimpleProbe):
native_class = jclass("android.widget.SeekBar")

@property
def position(self):
return (self.native.getProgress() - self._min) / (self._max - self._min)

def change(self, position):
self.native.setProgress(self._min + round(position * (self._max - self._min)))

@property
def _min(self):
return 0 if (Build.VERSION.SDK_INT < 26) else self.native.getMin()

@property
def _max(self):
return self.native.getMax()
1 change: 1 addition & 0 deletions changes/1687.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added a backend test app.
6 changes: 4 additions & 2 deletions iOS/src/toga_iOS/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,10 @@ def open_document(self, fileURL):
pass

def main_loop(self):
# Main loop is a no-op on iOS; the app loop is integrated with the
# main iOS event loop.
# Main loop is non-blocking on iOS. The app loop is integrated with the
# main iOS event loop, so this call will return; however, it will leave
# the app in a state such that asyncio events will be scheduled on the
# iOS event loop.
self.loop.run_forever_cooperatively(lifecycle=iOSLifecycle())

def set_main_window(self, window):
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ known_first_party = [
"toga_dummy",
"toga_gtk",
"toga_iOS",
"toga_test",
"toga_web",
"toga_winforms",
]
Expand Down
69 changes: 69 additions & 0 deletions testbed/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# OSX useful to ignore
*.DS_Store
.AppleDouble
.LSOverride

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

# C extensions
*.so

# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# IntelliJ Idea family of suites
.idea
*.iml
## File-based project format:
*.ipr
*.iws
## mpeltonen/sbt-idea plugin
.idea_modules/

# Briefcase build directories
iOS/
macOS/
windows/
android/
linux/
django/

# Briefcase log files
logs/
90 changes: 90 additions & 0 deletions testbed/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# This project was generated using template: https://github.com/beeware/briefcase-template and branch: v0.3.12
[tool.briefcase]
project_name = "Toga Testbed"
bundle = "org.beeware.toga"
version = "0.0.1"
url = "https://beeware.org"
license = "BSD license"
author = 'Tiberius Yak'
author_email = "[email protected]"

[tool.briefcase.app.testbed]
formal_name = "Toga Testbed"
description = "A testbed for Toga visual tests"
icon = "src/testbed/resources/testbed"
sources = [
'src/testbed',
]
test_sources = [
'tests',
]
requires = [
'../core',
]
test_requires = [
'pytest==7.2.0',
'pytest-asyncio==0.20.2',
]


[tool.briefcase.app.testbed.macOS]
requires = [
'../cocoa',
'std-nslog~=1.0.0'
]

[tool.briefcase.app.testbed.linux]
requires = [
'../gtk',
]

[tool.briefcase.app.testbed.linux.appimage]
system_requires = [
'gir1.2-webkit-3.0',
'libcairo2-dev',
'libgirepository1.0-dev',
'libgtk-3-dev',
'libpango1.0-dev',
'librsvg2-dev',
'libwebkitgtk-3.0-0',
]
linuxdeploy_plugins = [
'DEPLOY_GTK_VERSION=3 gtk',
]

[tool.briefcase.app.testbed.linux.flatpak]
flatpak_runtime = 'org.gnome.Platform'
flatpak_runtime_version = '42'
flatpak_sdk = 'org.gnome.Sdk'

[tool.briefcase.app.testbed.windows]
test_sources = [
'../winforms/tests_backend',
]
requires = [
'../winforms',
]

# Mobile deployments
[tool.briefcase.app.testbed.iOS]
requires = [
'../iOS',
'std-nslog~=1.0.0'
]

[tool.briefcase.app.testbed.android]
test_sources = [
'../android/tests_backend',
]
requires = [
'../android'
]

# TODO: replace with extractPackages
build_gradle_extra_content = "android.defaultConfig.python.pyc.src false"

[tool.briefcase.app.testbed.web]
requires = [
'../web'
]
style_framework = "Bootstrap v4.6"
Empty file added testbed/src/testbed/__init__.py
Empty file.
4 changes: 4 additions & 0 deletions testbed/src/testbed/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from testbed.app import main

if __name__ == "__main__":
main().main_loop()
Loading

0 comments on commit 1971d06

Please sign in to comment.