From f5ee74b67cbd209f80b5c8473e308d4ede182cbb Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Wed, 25 Sep 2024 23:49:11 -0700 Subject: [PATCH] test: cleanup ios --- .github/workflows/functional-test.yml | 4 +- test/functional/ios/applications_tests.py | 33 ----- test/functional/ios/hw_actions_tests.py | 38 ------ test/functional/ios/keyboard_tests.py | 87 ------------- test/unit/webdriver/app_test.py | 137 +++++++++++++++++++- test/unit/webdriver/device/keyboard_test.py | 39 +++++- test/unit/webdriver/device/lock_test.py | 78 ++++++++++- 7 files changed, 249 insertions(+), 167 deletions(-) delete mode 100644 test/functional/ios/applications_tests.py delete mode 100644 test/functional/ios/hw_actions_tests.py delete mode 100644 test/functional/ios/keyboard_tests.py diff --git a/.github/workflows/functional-test.yml b/.github/workflows/functional-test.yml index 06c17ede..bfa1b713 100644 --- a/.github/workflows/functional-test.yml +++ b/.github/workflows/functional-test.yml @@ -20,10 +20,8 @@ jobs: test_targets: - target: test/functional/ios/search_context/find_by_*.py test/functional/ios/remote_fs_tests.py test/functional/ios/safari_tests.py test/functional/ios/execute_driver_tests.py name: func_test_ios1 - - target: test/functional/ios/applications_tests.py test/functional/ios/hw_actions_tests.py test/functional/ios/keyboard_tests.py - name: func_test_ios2 - target: test/functional/ios/screen_record_tests.py test/functional/ios/webdriver_tests.py - name: func_test_ios3 + name: func_test_ios2 runs-on: macos-14 diff --git a/test/functional/ios/applications_tests.py b/test/functional/ios/applications_tests.py deleted file mode 100644 index 072059bf..00000000 --- a/test/functional/ios/applications_tests.py +++ /dev/null @@ -1,33 +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. - -from appium.webdriver.applicationstate import ApplicationState -from test.functional.ios.helper.test_helper import BaseTestCase -from test.functional.test_helper import wait_for_condition - -from .helper import desired_capabilities - - -class TestWebDriver(BaseTestCase): - def test_app_management(self) -> None: - # this only works in Xcode9+ - if float(desired_capabilities.get_desired_capabilities(desired_capabilities.BUNDLE_ID)['platformVersion']) < 11: - return - assert self.driver.query_app_state(desired_capabilities.BUNDLE_ID) == ApplicationState.RUNNING_IN_FOREGROUND - self.driver.background_app(-1) - assert wait_for_condition( - lambda: self.driver.query_app_state(desired_capabilities.BUNDLE_ID) < ApplicationState.RUNNING_IN_FOREGROUND - ), 'The app didn\'t go to background.' - self.driver.activate_app(desired_capabilities.BUNDLE_ID) - assert self.driver.query_app_state(desired_capabilities.BUNDLE_ID) == ApplicationState.RUNNING_IN_FOREGROUND diff --git a/test/functional/ios/hw_actions_tests.py b/test/functional/ios/hw_actions_tests.py deleted file mode 100644 index 86264b37..00000000 --- a/test/functional/ios/hw_actions_tests.py +++ /dev/null @@ -1,38 +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. - -from test.functional.ios.helper.test_helper import BaseTestCase - - -class TestHwActions(BaseTestCase): - def test_lock(self) -> None: - self.driver.lock(-1) - try: - assert self.driver.is_locked() - finally: - self.driver.unlock() - assert not self.driver.is_locked() - - def test_shake(self) -> None: - # TODO what can we assert about this? - self.driver.shake() - - def test_touch_id(self) -> None: - # nothing to assert, just verify that it doesn't blow up - self.driver.touch_id(True) - self.driver.touch_id(False) - - def test_toggle_touch_id_enrollment(self) -> None: - # nothing to assert, just verify that it doesn't blow up - self.driver.toggle_touch_id_enrollment() diff --git a/test/functional/ios/keyboard_tests.py b/test/functional/ios/keyboard_tests.py deleted file mode 100644 index d07e5e70..00000000 --- a/test/functional/ios/keyboard_tests.py +++ /dev/null @@ -1,87 +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. - -from typing import TYPE_CHECKING - -import pytest -from selenium.common.exceptions import NoSuchElementException - -from appium.webdriver.common.appiumby import AppiumBy -from test.functional.ios.helper.test_helper import BaseTestCase - -if TYPE_CHECKING: - from appium.webdriver.webelement import WebElement - - -class TestKeyboard(BaseTestCase): - def test_hide_keyboard(self) -> None: - self._move_to_textbox() - - el = self.driver.find_elements(by=AppiumBy.CLASS_NAME, value='XCUIElementTypeTextField')[0] - el.click() - el.send_keys('Testing') - - assert self._get_keyboard_el().is_displayed() - - self.driver.hide_keyboard(key_name='Done') - - with pytest.raises(NoSuchElementException): - self._get_keyboard_el() - - def test_hide_keyboard_presskey_strategy(self) -> None: - self._move_to_textbox() - - el = self.driver.find_elements(by=AppiumBy.CLASS_NAME, value='XCUIElementTypeTextField')[0] - el.click() - el.send_keys('Testing') - - assert self._get_keyboard_el().is_displayed() - - self.driver.hide_keyboard(strategy='pressKey', key='Done') - - with pytest.raises(NoSuchElementException): - self._get_keyboard_el() - - def test_hide_keyboard_no_key_name(self) -> None: - self._move_to_textbox() - - el = self.driver.find_elements(by=AppiumBy.CLASS_NAME, value='XCUIElementTypeTextField')[0] - el.click() - el.send_keys('Testing') - - assert self._get_keyboard_el().is_displayed() - - self.driver.hide_keyboard() - - with pytest.raises(NoSuchElementException): - self._get_keyboard_el() - - def test_is_keyboard_shown(self) -> None: - self._move_to_textbox() - - el = self.driver.find_elements(by=AppiumBy.CLASS_NAME, value='XCUIElementTypeTextField')[0] - el.click() - el.send_keys('Testing') - assert self.driver.is_keyboard_shown() - - def _get_keyboard_el(self) -> 'WebElement': - return self.driver.find_element(by=AppiumBy.CLASS_NAME, value='XCUIElementTypeKeyboard') - - def _move_to_textbox(self) -> None: - el1 = self.driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value='Sliders') - el2 = self.driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value='Buttons') - self.driver.scroll(el1, el2) - - # Click text fields - self.driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value='Text Fields').click() diff --git a/test/unit/webdriver/app_test.py b/test/unit/webdriver/app_test.py index 45367141..6fa773ee 100644 --- a/test/unit/webdriver/app_test.py +++ b/test/unit/webdriver/app_test.py @@ -16,10 +16,10 @@ from appium.webdriver.applicationstate import ApplicationState from appium.webdriver.webdriver import WebDriver -from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body +from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body, ios_w3c_driver -class TestWebDriverApp(object): +class TestWebDriverAppAndroid(object): @httpretty.activate def test_install_app(self): driver = android_w3c_driver() @@ -150,3 +150,136 @@ def test_app_strings_with_lang_and_file(self): 'script': 'mobile: getAppStrings', } == get_httpretty_request_body(httpretty.last_request()) assert 'You can\'t wipe my data, you are a monkey!' == result['monkey_wipe_data'], result + + +class TestWebDriverAppIOS(object): + @httpretty.activate + def test_install_app(self): + driver = ios_w3c_driver() + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') + result = driver.install_app('path/to/app') + + assert { + 'args': [{'app': 'path/to/app', 'appPath': 'path/to/app'}], + 'script': 'mobile: installApp', + } == get_httpretty_request_body(httpretty.last_request()) + assert isinstance(result, WebDriver) + + @httpretty.activate + def test_remove_app(self): + driver = ios_w3c_driver() + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') + result = driver.remove_app('com.app.id') + + assert { + 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], + 'script': 'mobile: removeApp', + } == get_httpretty_request_body(httpretty.last_request()) + assert isinstance(result, WebDriver) + + @httpretty.activate + def test_app_installed(self): + driver = ios_w3c_driver() + httpretty.register_uri( + httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}' + ) + result = driver.is_app_installed("com.app.id") + + assert { + 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], + 'script': 'mobile: isAppInstalled', + } == get_httpretty_request_body(httpretty.last_request()) + assert result is True + + @httpretty.activate + def test_terminate_app(self): + driver = ios_w3c_driver() + httpretty.register_uri( + httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}' + ) + result = driver.terminate_app("com.app.id") + + assert { + 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], + 'script': 'mobile: terminateApp', + } == get_httpretty_request_body(httpretty.last_request()) + assert result is True + + @httpretty.activate + def test_activate_app(self): + driver = ios_w3c_driver() + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') + result = driver.activate_app("com.app.id") + + assert { + 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], + 'script': 'mobile: activateApp', + } == get_httpretty_request_body(httpretty.last_request()) + assert isinstance(result, WebDriver) + + @httpretty.activate + def test_background_app(self): + driver = ios_w3c_driver() + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') + result = driver.background_app(0) + + assert {'args': [{'seconds': 0}], 'script': 'mobile: backgroundApp'} == get_httpretty_request_body( + httpretty.last_request() + ) + assert isinstance(result, WebDriver) + + @httpretty.activate + def test_query_app_state(self): + driver = ios_w3c_driver() + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": 3}') + result = driver.query_app_state('com.app.id') + + assert { + 'args': [{'appId': 'com.app.id', 'bundleId': 'com.app.id'}], + 'script': 'mobile: queryAppState', + } == get_httpretty_request_body(httpretty.last_request()) + assert result is ApplicationState.RUNNING_IN_BACKGROUND + + @httpretty.activate + def test_app_strings(self): + driver = ios_w3c_driver() + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + body='{"value": {"monkey_wipe_data": "You can\'t wipe my data, you are a monkey!"} }', + ) + result = driver.app_strings() + + assert {'args': [{}], 'script': 'mobile: getAppStrings'} == get_httpretty_request_body(httpretty.last_request()) + assert 'You can\'t wipe my data, you are a monkey!' == result['monkey_wipe_data'], result + + @httpretty.activate + def test_app_strings_with_lang(self): + driver = ios_w3c_driver() + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + body='{"value": {"monkey_wipe_data": "You can\'t wipe my data, you are a monkey!"} }', + ) + result = driver.app_strings('en') + + assert {'args': [{'language': 'en'}], 'script': 'mobile: getAppStrings'} == get_httpretty_request_body( + httpretty.last_request() + ) + assert 'You can\'t wipe my data, you are a monkey!' == result['monkey_wipe_data'], result + + @httpretty.activate + def test_app_strings_with_lang_and_file(self): + driver = ios_w3c_driver() + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/execute/sync'), + body='{"value": {"monkey_wipe_data": "You can\'t wipe my data, you are a monkey!"} }', + ) + result = driver.app_strings('en', 'some_file') + + assert { + 'args': [{'language': 'en', 'stringFile': 'some_file'}], + 'script': 'mobile: getAppStrings', + } == get_httpretty_request_body(httpretty.last_request()) + assert 'You can\'t wipe my data, you are a monkey!' == result['monkey_wipe_data'], result diff --git a/test/unit/webdriver/device/keyboard_test.py b/test/unit/webdriver/device/keyboard_test.py index e3401839..79579fb9 100644 --- a/test/unit/webdriver/device/keyboard_test.py +++ b/test/unit/webdriver/device/keyboard_test.py @@ -15,10 +15,10 @@ import httpretty from appium.webdriver.webdriver import WebDriver -from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body +from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body, ios_w3c_driver -class TestWebDriverKeyboard(object): +class TestWebDriverKeyboardAndroid(object): @httpretty.activate def test_hide_keyboard(self): driver = android_w3c_driver() @@ -96,3 +96,38 @@ def test_long_press_keycode_with_flags(self): driver.long_press_keycode(86, metastate=0x00000001 | 0x00200000, flags=0x20 | 0x00000004 | 0x00000008), WebDriver, ) + + +class TestWebDriverKeyboardIOS(object): + @httpretty.activate + def test_hide_keyboard(self): + driver = ios_w3c_driver() + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) + assert isinstance(driver.hide_keyboard(), WebDriver) + assert {'args': [{}], 'script': 'mobile: hideKeyboard'} == get_httpretty_request_body(httpretty.last_request()) + + @httpretty.activate + def test_hide_keyboard_with_key(self): + driver = ios_w3c_driver() + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) + assert isinstance(driver.hide_keyboard(key_name='Done'), WebDriver) + assert {'args': [{'keys': ['Done']}], 'script': 'mobile: hideKeyboard'} == get_httpretty_request_body( + httpretty.last_request() + ) + + @httpretty.activate + def test_hide_keyboard_with_key_and_strategy(self): + driver = ios_w3c_driver() + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) + assert isinstance(driver.hide_keyboard(strategy='pressKey', key='Done'), WebDriver) + # only 'keys' works + assert {'args': [{'keys': ['Done']}], 'script': 'mobile: hideKeyboard'} == get_httpretty_request_body( + httpretty.last_request() + ) + + @httpretty.activate + def test_is_keyboard_shown(self): + driver = ios_w3c_driver() + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) + driver.is_keyboard_shown(), WebDriver + assert {'script': 'mobile: isKeyboardShown', 'args': []} == get_httpretty_request_body(httpretty.last_request()) diff --git a/test/unit/webdriver/device/lock_test.py b/test/unit/webdriver/device/lock_test.py index 1e8ce09c..7a357a70 100644 --- a/test/unit/webdriver/device/lock_test.py +++ b/test/unit/webdriver/device/lock_test.py @@ -15,10 +15,10 @@ import httpretty from appium.webdriver.webdriver import WebDriver -from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body +from test.unit.helper.test_helper import android_w3c_driver, appium_command, get_httpretty_request_body, ios_w3c_driver -class TestWebDriverLock(object): +class TestWebDriverLockAndroid(object): @httpretty.activate def test_lock(self): driver = android_w3c_driver() @@ -71,3 +71,77 @@ def test_unlock(self): ) httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) assert isinstance(driver.unlock(), WebDriver) + + +class TestWebDriverLockIOS(object): + @httpretty.activate + def test_lock(self): + driver = ios_w3c_driver() + httpretty.register_uri( + httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}' + ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') + driver.lock(1) + + d = get_httpretty_request_body(httpretty.last_request()) + assert d.get('seconds', d['args'][0]['seconds']) == 1 + + @httpretty.activate + def test_lock_no_args(self): + driver = ios_w3c_driver() + httpretty.register_uri( + httpretty.POST, appium_command('/session/1234567890/appium/device/lock'), body='{"value": ""}' + ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": ""}') + driver.lock() + + @httpretty.activate + def test_islocked_false(self): + driver = ios_w3c_driver() + httpretty.register_uri( + httpretty.POST, appium_command('/session/1234567890/appium/device/is_locked'), body='{"value": false}' + ) + httpretty.register_uri( + httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": false}' + ) + assert driver.is_locked() is False + + @httpretty.activate + def test_islocked_true(self): + driver = ios_w3c_driver() + httpretty.register_uri( + httpretty.POST, appium_command('/session/1234567890/appium/device/is_locked'), body='{"value": true}' + ) + httpretty.register_uri( + httpretty.POST, appium_command('/session/1234567890/execute/sync'), body='{"value": true}' + ) + assert driver.is_locked() is True + + @httpretty.activate + def test_unlock(self): + driver = ios_w3c_driver() + httpretty.register_uri( + httpretty.POST, + appium_command('/session/1234567890/appium/device/unlock'), + ) + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) + assert isinstance(driver.unlock(), WebDriver) + + @httpretty.activate + def test_touch_id(self): + driver = ios_w3c_driver() + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) + assert isinstance(driver.touch_id(True), WebDriver) + assert { + 'script': 'mobile: sendBiometricMatch', + 'args': [{'match': True, 'type': 'touchId'}], + } == get_httpretty_request_body(httpretty.last_request()) + + @httpretty.activate + def test_touch_id(self): + driver = ios_w3c_driver() + httpretty.register_uri(httpretty.POST, appium_command('/session/1234567890/execute/sync')) + assert isinstance(driver.toggle_touch_id_enrollment(), WebDriver) + assert {'script': 'mobile: enrollBiometric', 'args': [{'isEnabled': True}]} == get_httpretty_request_body( + httpretty.last_request() + )