diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index ada561b9..06c17ede 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -91,16 +91,8 @@ jobs: fail-fast: false matrix: test_targets: - - target: test/functional/android/device_time_tests.py test/functional/android/search_context/find_by_*.py - name: func_test_android1 - - target: test/functional/android/keyboard_tests.py test/functional/android/location_tests.py - name: func_test_android2 - target: test/functional/android/appium_service_tests.py test/functional/android/chrome_tests.py - name: func_test_android3 - - target: test/functional/android/finger_print_tests.py test/functional/android/screen_record_tests.py test/functional/android/settings_tests.py - name: func_test_android4 - - target: test/functional/android/remote_fs_tests.py test/functional/android/log_event_tests.py - name: func_test_android5 + name: func_test_android1 runs-on: ubuntu-latest @@ -126,9 +118,8 @@ jobs: - run: | appium driver install uiautomator2 appium driver install espresso - appium plugin install images appium plugin install execute-driver - nohup appium --use-plugins=images,execute-driver --relaxed-security --log-timestamp --log-no-colors 2>&1 > appium.log & + nohup appium --use-plugins=execute-driver --relaxed-security --log-timestamp --log-no-colors 2>&1 > appium.log & - name: Enable KVM group perms run: | diff --git a/test/functional/android/device_time_tests.py b/test/functional/android/device_time_tests.py deleted file mode 100644 index b5d576fb..00000000 --- a/test/functional/android/device_time_tests.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from dateutil.parser import parse - -from .helper.test_helper import BaseTestCase - - -class TestDeviceTime(BaseTestCase): - def test_device_time(self) -> None: - date_time = self.driver.device_time - # convert to date ought to work - parse(date_time) diff --git a/test/functional/android/file/find_by_image_failure.png b/test/functional/android/file/find_by_image_failure.png deleted file mode 100644 index 5ea155cc..00000000 Binary files a/test/functional/android/file/find_by_image_failure.png and /dev/null differ diff --git a/test/functional/android/file/find_by_image_success.png b/test/functional/android/file/find_by_image_success.png deleted file mode 100644 index 3916d73d..00000000 Binary files a/test/functional/android/file/find_by_image_success.png and /dev/null differ diff --git a/test/functional/android/file/test_file.txt b/test/functional/android/file/test_file.txt deleted file mode 100644 index 4fac12a9..00000000 --- a/test/functional/android/file/test_file.txt +++ /dev/null @@ -1 +0,0 @@ -HEllo diff --git a/test/functional/android/file/test_image.jpg b/test/functional/android/file/test_image.jpg deleted file mode 100644 index 6434234f..00000000 Binary files a/test/functional/android/file/test_image.jpg and /dev/null differ diff --git a/test/functional/android/finger_print_tests.py b/test/functional/android/finger_print_tests.py deleted file mode 100644 index 23fe9d3a..00000000 --- a/test/functional/android/finger_print_tests.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from .helper.test_helper import BaseTestCase - - -class TestFingerPrint(BaseTestCase): - def test_finger_print(self) -> None: - try: - self.driver.finger_print(1) - except Exception: - assert False, "Sould not raise any exceptions" diff --git a/test/functional/android/keyboard_tests.py b/test/functional/android/keyboard_tests.py deleted file mode 100644 index 5e1ebe6a..00000000 --- a/test/functional/android/keyboard_tests.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from .helper.test_helper import BaseTestCase - - -class TestKeyboard(BaseTestCase): - def test_press_keycode(self) -> None: - # TODO not sure how to test this. - self.driver.press_keycode(176) - - def test_long_press_keycode(self) -> None: - # TODO not sure how to test this. - self.driver.long_press_keycode(176) diff --git a/test/functional/android/location_tests.py b/test/functional/android/location_tests.py deleted file mode 100644 index 30cd7880..00000000 --- a/test/functional/android/location_tests.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from .helper.test_helper import BaseTestCase - - -class TestLocation(BaseTestCase): - def test_toggle_location_services(self) -> None: - self.driver.toggle_location_services() # TODO Add assert diff --git a/test/functional/android/log_event_tests.py b/test/functional/android/log_event_tests.py deleted file mode 100644 index 9ad0b53d..00000000 --- a/test/functional/android/log_event_tests.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from .helper.test_helper import BaseTestCase - - -class TestLogEvent(BaseTestCase): - def test_log_event(self) -> None: - vendor = 'appium' - event = 'funEvent' - self.driver.log_event(vendor, event) - assert f'{vendor}:{event}' in self.driver.get_events().keys() diff --git a/test/functional/android/remote_fs_tests.py b/test/functional/android/remote_fs_tests.py deleted file mode 100644 index c11d4c2b..00000000 --- a/test/functional/android/remote_fs_tests.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import base64 -import os -import random -from io import BytesIO -from zipfile import ZipFile - -from .helper.test_helper import BaseTestCase - - -class TestRemoteFs(BaseTestCase): - def test_push_pull_file(self) -> None: - dest_path = '/data/local/tmp/test_push_file.txt' - data = bytes('This is the contents of the file to push to the device.', 'utf-8') - - self.driver.push_file(dest_path, base64.b64encode(data).decode('utf-8')) - data_ret = base64.b64decode(self.driver.pull_file(dest_path)) - - assert data == data_ret - - def test_pull_folder(self) -> None: - data = bytes('random string data {}'.format(random.randint(0, 1000)), 'utf-8') - dest_dir = '/data/local/tmp/' - - for filename in ['1.txt', '2.txt']: - self.driver.push_file(os.path.join(dest_dir, filename), base64.b64encode(data).decode('utf-8')) - - folder = self.driver.pull_folder(dest_dir) - - with ZipFile(BytesIO(base64.b64decode(folder))) as fzip: - for filename in ['tmp/1.txt', 'tmp/2.txt']: - # e.g. in the fzip.namelist(): - # ['tmp/', 'tmp/.studio/', 'tmp/.studio/process-tracker', 'tmp/1.txt', 'tmp/2.txt', - # 'tmp/chrome-command-line', 'tmp/espresso.apppackage', 'tmp/remote.txt', - # 'tmp/test_file.txt', 'tmp/test_image.jpg', 'tmp/test_push_file.txt'] - assert filename in fzip.namelist() - - def test_push_file_with_src_path(self) -> None: - test_files = ['test_image.jpg', 'test_file.txt'] - for file_name in test_files: - src_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'file', file_name) - dest_path = os.path.join('/data/local/tmp/', file_name) - - with open(src_path, 'rb') as fr: - original_data = fr.read() - - self.driver.push_file(dest_path, source_path=src_path) - new_data = base64.b64decode(self.driver.pull_file(dest_path)) - assert original_data == new_data diff --git a/test/functional/android/screen_record_tests.py b/test/functional/android/screen_record_tests.py deleted file mode 100644 index 49618a89..00000000 --- a/test/functional/android/screen_record_tests.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from time import sleep - -from .helper.test_helper import BaseTestCase - - -class TestScreenRecord(BaseTestCase): - def test_screen_record(self) -> None: - self.driver.start_recording_screen(timeLimit=10, forcedRestart=True) - sleep(10) - result = self.driver.stop_recording_screen() - assert len(result) > 0 diff --git a/test/functional/android/search_context/__init__.py b/test/functional/android/search_context/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/functional/android/search_context/find_by_accessibility_id_tests.py b/test/functional/android/search_context/find_by_accessibility_id_tests.py deleted file mode 100644 index 4f9dc3fe..00000000 --- a/test/functional/android/search_context/find_by_accessibility_id_tests.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pytest - -from appium.webdriver.common.appiumby import AppiumBy -from appium.webdriver.webelement import WebElement -from test.functional.android.helper.test_helper import BaseTestCase, is_ci -from test.functional.test_helper import wait_for_element - - -class TestFindByAccessibilityID(BaseTestCase): - def test_find_single_element(self) -> None: - wait_for_element(self.driver, AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("Accessibility")').click() - wait_for_element( - self.driver, AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("Accessibility Node Querying")' - ).click() - el = wait_for_element(self.driver, AppiumBy.ACCESSIBILITY_ID, 'Task Take out Trash') - assert el is not None - - def test_find_multiple_elements(self) -> None: - els = self.driver.find_elements(by=AppiumBy.ACCESSIBILITY_ID, value='Accessibility') - assert isinstance(els, list) - - @pytest.mark.skipif(condition=is_ci(), reason='Need to fix flaky test during running on CI') - def test_element_find_single_element(self) -> None: - wait_for_element(self.driver, AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("Accessibility")').click() - wait_for_element( - self.driver, AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("Accessibility Node Querying")' - ).click() - el = wait_for_element(self.driver, AppiumBy.CLASS_NAME, 'android.widget.ListView') - - sub_el: WebElement = el.find_element(by=AppiumBy.ACCESSIBILITY_ID, value='Task Take out Trash') - assert sub_el is not None - - def test_element_find_multiple_elements(self) -> None: - wait_for_element(self.driver, AppiumBy.CLASS_NAME, 'android.widget.ListView') - el = self.driver.find_element(by=AppiumBy.CLASS_NAME, value='android.widget.ListView') - sub_els: list = el.find_elements(by=AppiumBy.ACCESSIBILITY_ID, value='Animation') - assert isinstance(sub_els, list) diff --git a/test/functional/android/search_context/find_by_image_tests.py b/test/functional/android/search_context/find_by_image_tests.py deleted file mode 100644 index 94970fa9..00000000 --- a/test/functional/android/search_context/find_by_image_tests.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import base64 - -import pytest -from selenium.common.exceptions import TimeoutException - -from appium import webdriver -from appium.options.common import AppiumOptions -from appium.webdriver.common.appiumby import AppiumBy -from test.functional.android.helper import desired_capabilities -from test.functional.test_helper import wait_for_element -from test.helpers.constants import SERVER_URL_BASE - - -class TestFindByImage(object): - def setup_method(self) -> None: - caps = desired_capabilities.get_desired_capabilities('ApiDemos-debug.apk.zip') - self.driver = webdriver.Remote(SERVER_URL_BASE, options=AppiumOptions().load_capabilities(caps)) - - # relax template matching - self.driver.update_settings( - { - 'fixImageFindScreenshotDims': False, - 'fixImageTemplateSize': True, - 'autoUpdateImageElementPosition': True, - 'fixImageTemplateScale': True, - 'imageMatchThreshold': 0.8, - } - ) - - def teardown_method(self) -> None: - self.driver.quit() - - def test_find_based_on_image_template(self) -> None: - image_path = desired_capabilities.PATH('file/find_by_image_success.png') - with open(image_path, 'rb') as png_file: - b64_data = base64.b64encode(png_file.read()).decode('UTF-8') - - el = wait_for_element(self.driver, AppiumBy.IMAGE, b64_data) - size = el.size - assert size['width'] is not None - assert size['height'] is not None - loc = el.location - assert loc['x'] is not None - assert loc['y'] is not None - rect = el.rect - assert rect['width'] is not None - assert rect['height'] is not None - assert rect['x'] is not None - assert rect['y'] is not None - assert el.is_displayed() - el.click() - wait_for_element(self.driver, AppiumBy.ACCESSIBILITY_ID, 'Alarm') - - def test_find_multiple_elements_by_image_just_returns_one(self) -> None: - wait_for_element(self.driver, AppiumBy.ACCESSIBILITY_ID, 'App') - image_path = desired_capabilities.PATH('file/find_by_image_success.png') - with open(image_path, 'rb') as png_file: - b64_data = base64.b64encode(png_file.read()).decode('UTF-8') - els = self.driver.find_elements(AppiumBy.IMAGE, b64_data) - els[0].click() - wait_for_element(self.driver, AppiumBy.ACCESSIBILITY_ID, 'Alarm') - - def test_find_throws_no_such_element(self) -> None: - image_path = desired_capabilities.PATH('file/find_by_image_failure.png') - with open(image_path, 'rb') as png_file: - b64_data = base64.b64encode(png_file.read()).decode('UTF-8') - - with pytest.raises(TimeoutException): - wait_for_element(self.driver, AppiumBy.IMAGE, b64_data, timeout_sec=3) diff --git a/test/functional/android/search_context/find_by_uiautomator_tests.py b/test/functional/android/search_context/find_by_uiautomator_tests.py deleted file mode 100644 index a8819bc0..00000000 --- a/test/functional/android/search_context/find_by_uiautomator_tests.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pytest - -from appium.webdriver.common.appiumby import AppiumBy -from appium.webdriver.webelement import WebElement -from test.functional.android.helper.test_helper import BaseTestCase - - -@pytest.mark.skip(reason='Need to fix flaky test') -class TestFindByUIAutomator(BaseTestCase): - def test_find_single_element(self) -> None: - el = self.driver.find_element(by=AppiumBy.ANDROID_UIAUTOMATOR, value='new UiSelector().text("Animation")') - assert el is not None - - def test_find_multiple_elements(self) -> None: - els = self.driver.find_elements(by=AppiumBy.ANDROID_UIAUTOMATOR, value='new UiSelector().clickable(true)') - assert isinstance(els, list) - - def test_element_find_single_element(self) -> None: - el = self.driver.find_element(by=AppiumBy.CLASS_NAME, value='android.widget.ListView') - - sub_el: WebElement = el.find_element( - by=AppiumBy.ANDROID_UIAUTOMATOR, value='new UiSelector().description("Animation")' - ) - assert sub_el is not None - - def test_element_find_multiple_elements(self) -> None: - el = self.driver.find_element(by=AppiumBy.CLASS_NAME, value='android.widget.ListView') - - sub_els = el.find_elements( - by=AppiumBy.ANDROID_UIAUTOMATOR, value='new UiSelector().clickable(true)' - ) # type: list - assert isinstance(sub_els, list) - - def test_scroll_into_view(self) -> None: - el = self.driver.find_element( - by=AppiumBy.ANDROID_UIAUTOMATOR, - value='new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("Views").instance(0));', - ) - el.click() - # TODO Add assert diff --git a/test/functional/android/search_context/find_by_view_matcher_tests.py b/test/functional/android/search_context/find_by_view_matcher_tests.py deleted file mode 100644 index 47a2eb8d..00000000 --- a/test/functional/android/search_context/find_by_view_matcher_tests.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json - -import pytest -from selenium.common.exceptions import WebDriverException - -from appium import webdriver -from appium.options.common import AppiumOptions -from appium.webdriver.common.appiumby import AppiumBy -from test.functional.android.helper.test_helper import BaseTestCase, desired_capabilities, is_ci -from test.helpers.constants import SERVER_URL_BASE - - -class TestFindByViewMatcher(BaseTestCase): - # Override - def setup_method(self, method) -> None: # type: ignore - caps = desired_capabilities.get_desired_capabilities('ApiDemos-debug.apk.zip') - caps['automationName'] = 'Espresso' - self.driver = webdriver.Remote(SERVER_URL_BASE, options=AppiumOptions().load_capabilities(caps)) - if is_ci(): - self.driver.start_recording_screen() - - def test_find_single_element(self) -> None: - el = self.driver.find_element( - by=AppiumBy.ANDROID_VIEW_MATCHER, - value=json.dumps({'name': 'withText', 'args': ['Accessibility'], 'class': 'ViewMatchers'}), - ) - assert el.text == 'Accessibility' - - def test_find_single_element_ful_class_name(self) -> None: - el = self.driver.find_element( - by=AppiumBy.ANDROID_VIEW_MATCHER, - value=json.dumps( - {'name': 'withText', 'args': ['Accessibility'], 'class': 'androidx.test.espresso.matcher.ViewMatchers'} - ), - ) - assert el.text == 'Accessibility' - - def test_find_single_element_using_hamcrest_matcher(self) -> None: - el = self.driver.find_element( - by=AppiumBy.ANDROID_VIEW_MATCHER, - value=json.dumps( - { - 'name': 'withText', - 'args': {'name': 'containsString', 'args': 'Animati', 'class': 'org.hamcrest.Matchers'}, - 'class': 'ViewMatchers', - } - ), - ) - assert el.text == 'Animation' - - # androidx.test.espresso.AmbiguousViewMatcherException: - # 'with text: a string containing "Access"' matches multiple views in the hierarchy. - def test_find_multiple_elements(self) -> None: - el = self.driver.find_element( - by=AppiumBy.ANDROID_VIEW_MATCHER, - value=json.dumps({'name': 'withSubstring', 'args': ['Access'], 'class': 'ViewMatchers'}), - ) - assert el.text == "Access'ibility" diff --git a/test/functional/android/settings_tests.py b/test/functional/android/settings_tests.py deleted file mode 100644 index 66afa953..00000000 --- a/test/functional/android/settings_tests.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from .helper.test_helper import BaseTestCase - - -class TestSettings(BaseTestCase): - def test_get_settings(self) -> None: - settings = self.driver.get_settings() - assert settings is not None - - def test_update_settings(self) -> None: - self.driver.update_settings({'waitForIdleTimeout': 10001}) - settings = self.driver.get_settings() - assert settings['waitForIdleTimeout'] == 10001