Skip to content

Commit 523523d

Browse files
test: Update iOS e2e tests
1 parent b22b031 commit 523523d

File tree

6 files changed

+165
-185
lines changed

6 files changed

+165
-185
lines changed

test/apps/TestApp.app.zip

-22.2 KB
Binary file not shown.

test/apps/UICatalog.app.zip

-1.75 MB
Binary file not shown.

test/functional/ios/helper/desired_capabilities.py

Lines changed: 0 additions & 84 deletions
This file was deleted.
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#!/usr/bin/env python
2+
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
from dataclasses import dataclass
17+
from typing import Optional
18+
19+
from appium.options.ios import XCUITestOptions
20+
21+
# Returns abs path relative to this file and not cwd
22+
23+
24+
def PATH(p: str) -> str:
25+
return os.path.abspath(os.path.join(os.path.dirname(__file__), p))
26+
27+
28+
def make_options(app: Optional[str] = None) -> XCUITestOptions:
29+
"""Get XCUITest options configured for iOS testing with parallel execution support."""
30+
options = XCUITestOptions()
31+
32+
# Set basic iOS capabilities
33+
options.device_name = iphone_device_name()
34+
options.platform_version = os.getenv('IOS_VERSION') or '17.4'
35+
options.allow_touch_id_enroll = True
36+
options.wda_local_port = wda_port()
37+
options.simple_is_visible_check = True
38+
39+
if app is not None:
40+
options.app = PATH(os.path.join('../../..', 'apps', app))
41+
42+
local_prebuilt_wda = os.getenv('LOCAL_PREBUILT_WDA')
43+
if local_prebuilt_wda:
44+
options.use_preinstalled_wda = True
45+
options.prebuilt_wda_path = local_prebuilt_wda
46+
47+
return options
48+
49+
50+
@dataclass
51+
class WorkerInfo:
52+
"""Information about the current test worker in parallel execution."""
53+
54+
worker_number: Optional[int]
55+
total_workers: Optional[int]
56+
57+
@property
58+
def is_parallel(self) -> bool:
59+
"""Check if running in parallel mode."""
60+
return self.worker_number is not None and self.total_workers is not None
61+
62+
63+
def _get_worker_info() -> WorkerInfo:
64+
"""
65+
Get current worker number and total worker count from pytest-xdist environment variables.
66+
67+
Returns:
68+
WorkerInfo: Worker information or None values if not running in parallel
69+
"""
70+
worker_number = os.getenv('PYTEST_XDIST_WORKER')
71+
worker_count = os.getenv('PYTEST_XDIST_WORKER_COUNT')
72+
73+
if worker_number and worker_count:
74+
# Extract number from worker string like 'gw0', 'gw1', etc.
75+
try:
76+
worker_num = int(worker_number.replace('gw', ''))
77+
total_workers = int(worker_count)
78+
return WorkerInfo(worker_number=worker_num, total_workers=total_workers)
79+
except (ValueError, AttributeError):
80+
pass
81+
82+
return WorkerInfo(worker_number=None, total_workers=None)
83+
84+
85+
def wda_port() -> int:
86+
"""
87+
Get a unique WDA port for the current worker.
88+
Uses base port 8100 and increments by worker number.
89+
"""
90+
worker_info = _get_worker_info()
91+
return 8100 + (worker_info.worker_number or 0)
92+
93+
94+
def iphone_device_name() -> str:
95+
"""
96+
Get a unique device name for the current worker.
97+
Uses the base device name and appends the port number for uniqueness.
98+
"""
99+
prefix = os.getenv('IPHONE_MODEL') or 'iPhone 15 Plus'
100+
worker_info = _get_worker_info()
101+
102+
if worker_info.is_parallel:
103+
port = wda_port()
104+
return f'{prefix} - {port}'
105+
106+
return prefix

test/functional/ios/helper/test_helper.py

Lines changed: 0 additions & 47 deletions
This file was deleted.

test/functional/ios/safari_tests.py

Lines changed: 59 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -13,62 +13,67 @@
1313
# limitations under the License.
1414

1515
import time
16+
from typing import TYPE_CHECKING, Generator
17+
18+
import pytest
1619

1720
from appium import webdriver
18-
from appium.options.common import AppiumOptions
1921
from appium.webdriver.client_config import AppiumClientConfig
2022
from test.helpers.constants import SERVER_URL_BASE
2123

22-
from .helper.desired_capabilities import get_desired_capabilities
23-
24-
25-
class TestSafari:
26-
def setup_method(self) -> None:
27-
caps = get_desired_capabilities()
28-
caps.update(
29-
{
30-
'bundleId': 'com.apple.mobilesafari',
31-
'nativeWebTap': True,
32-
'safariIgnoreFraudWarning': True,
33-
'webviewConnectTimeout': 100000,
34-
}
35-
)
36-
client_config = AppiumClientConfig(remote_server_addr=SERVER_URL_BASE)
37-
client_config.timeout = 600
38-
self.driver = webdriver.Remote(options=AppiumOptions().load_capabilities(caps), client_config=client_config)
39-
40-
# Fresh iOS 17.4 simulator may not show up the webview context with "safari"
41-
# after a fresh simlator instance creation.
42-
# Re-launch the process could be a workaround in my debugging.
43-
self.driver.terminate_app('com.apple.mobilesafari')
44-
self.driver.activate_app('com.apple.mobilesafari')
45-
46-
def teardown_method(self) -> None:
47-
self.driver.quit()
48-
49-
def test_context(self) -> None:
50-
contexts = self.driver.contexts
51-
assert 'NATIVE_APP' == contexts[0]
52-
assert contexts[1].startswith('WEBVIEW_')
53-
self.driver.switch_to.context(contexts[1])
54-
assert 'WEBVIEW_' in self.driver.current_context
55-
56-
def test_get(self) -> None:
57-
ok = False
58-
contexts = self.driver.contexts
59-
for context in contexts:
60-
if context.startswith('WEBVIEW_'):
61-
self.driver.switch_to.context(context)
62-
ok = True
63-
break
64-
65-
if ok is False:
66-
assert False, 'Could not set WEBVIEW context'
67-
68-
self.driver.get('http://google.com')
69-
for _ in range(5):
70-
time.sleep(0.5)
71-
if 'Google' == self.driver.title:
72-
return
73-
74-
assert False, 'The title was wrong'
24+
from .helper.options import make_options
25+
26+
if TYPE_CHECKING:
27+
from appium.webdriver.webdriver import WebDriver
28+
29+
30+
@pytest.fixture
31+
def driver() -> Generator['WebDriver', None, None]:
32+
"""Create and configure Safari driver for testing."""
33+
options = make_options()
34+
options.bundle_id = 'com.apple.mobilesafari'
35+
options.native_web_tap = True
36+
options.safari_ignore_fraud_warning = True
37+
options.webview_connect_timeout = 100000
38+
39+
client_config = AppiumClientConfig(remote_server_addr=SERVER_URL_BASE)
40+
client_config.timeout = 600
41+
driver = webdriver.Remote(options=options, client_config=client_config)
42+
43+
# Fresh iOS 17.4 simulator may not show up the webview context with "safari"
44+
# after a fresh simlator instance creation.
45+
# Re-launch the process could be a workaround in my debugging.
46+
driver.terminate_app('com.apple.mobilesafari')
47+
driver.activate_app('com.apple.mobilesafari')
48+
49+
yield driver
50+
51+
driver.quit()
52+
53+
54+
def test_context(driver: 'WebDriver') -> None:
55+
"""Test Safari context switching."""
56+
contexts = driver.contexts
57+
assert 'NATIVE_APP' == contexts[0]
58+
assert contexts[1].startswith('WEBVIEW_')
59+
driver.switch_to.context(contexts[1])
60+
assert 'WEBVIEW_' in driver.current_context
61+
62+
63+
def test_navigation(driver: 'WebDriver') -> None:
64+
"""Test Safari navigation to Google."""
65+
contexts = driver.contexts
66+
for context in contexts:
67+
if context.startswith('WEBVIEW_'):
68+
driver.switch_to.context(context)
69+
break
70+
else:
71+
pytest.fail('Could not set WEBVIEW context')
72+
73+
driver.get('http://google.com')
74+
for _ in range(5):
75+
time.sleep(0.5)
76+
if 'Google' == driver.title:
77+
return
78+
else:
79+
pytest.fail('The title was wrong')

0 commit comments

Comments
 (0)