Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
25 changes: 20 additions & 5 deletions appium/webdriver/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from typing import Any, Callable, Dict, List, Optional, Tuple, Union

from selenium import webdriver
from selenium.common.exceptions import InvalidArgumentException, WebDriverException
from selenium.common.exceptions import InvalidArgumentException, SessionNotCreatedException, WebDriverException
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.command import Command as RemoteCommand
from selenium.webdriver.remote.remote_connection import RemoteConnection
Expand Down Expand Up @@ -317,10 +317,25 @@ def start_session(self, capabilities: Union[Dict, AppiumOptions], browser_profil

w3c_caps = AppiumOptions.as_w3c(capabilities) if isinstance(capabilities, dict) else capabilities.to_w3c()
response = self.execute(RemoteCommand.NEW_SESSION, w3c_caps)
if 'sessionId' not in response:
response = response['value']
self.session_id = response['sessionId']
self.caps = response.get('value') or response.get('capabilities')
# https://w3c.github.io/webdriver/#new-session
if not isinstance(response, dict):
raise SessionNotCreatedException(
f'A valid W3C session creation response must be a dictionary. Got "{response}" instead'
)
# Due to a W3C spec parsing misconception some servers
# pack the createSession response stuff into 'value' dictionary and
# some other put it to the top level of the response JSON nesting hierarchy
get_response_value: Callable[[str], Optional[Any]] = lambda key: response.get(key) or (
response['value'].get(key) if isinstance(response.get('value'), dict) else None
)
session_id = get_response_value('sessionId')
if not session_id:
raise SessionNotCreatedException(
f'A valid W3C session creation response must contain a non-empty "sessionId" entry. '
f'Got "{response}" instead'
)
self.session_id = session_id
self.caps = get_response_value('capabilities') or {}

def find_element(self, by: str = AppiumBy.ID, value: Union[str, Dict] = None) -> MobileWebElement:
"""
Expand Down
67 changes: 30 additions & 37 deletions test/unit/helper/test_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,29 +50,27 @@ def android_w3c_driver() -> 'WebDriver':

response_body_json = json.dumps(
{
'value': {
'sessionId': '1234567890',
'capabilities': {
'platform': 'LINUX',
'desired': {
'platformName': 'Android',
'automationName': 'uiautomator2',
'platformVersion': '7.1.1',
'deviceName': 'Android Emulator',
'app': '/test/apps/ApiDemos-debug.apk',
},
'sessionId': '1234567890',
'capabilities': {
'platform': 'LINUX',
'desired': {
'platformName': 'Android',
'automationName': 'uiautomator2',
'platformVersion': '7.1.1',
'deviceName': 'emulator-5554',
'deviceName': 'Android Emulator',
'app': '/test/apps/ApiDemos-debug.apk',
'deviceUDID': 'emulator-5554',
'appPackage': 'io.appium.android.apis',
'appWaitPackage': 'io.appium.android.apis',
'appActivity': 'io.appium.android.apis.ApiDemos',
'appWaitActivity': 'io.appium.android.apis.ApiDemos',
},
}
'platformName': 'Android',
'automationName': 'uiautomator2',
'platformVersion': '7.1.1',
'deviceName': 'emulator-5554',
'app': '/test/apps/ApiDemos-debug.apk',
'deviceUDID': 'emulator-5554',
'appPackage': 'io.appium.android.apis',
'appWaitPackage': 'io.appium.android.apis',
'appActivity': 'io.appium.android.apis.ApiDemos',
'appWaitActivity': 'io.appium.android.apis.ApiDemos',
},
}
)

Expand All @@ -95,18 +93,15 @@ def ios_w3c_driver() -> 'WebDriver':
Returns:
`webdriver.webdriver.WebDriver`: An instance of WebDriver
"""

response_body_json = json.dumps(
{
'value': {
'sessionId': '1234567890',
'capabilities': {
'device': 'iphone',
'browserName': 'UICatalog',
'sdkVersion': '11.4',
'CFBundleIdentifier': 'com.example.apple-samplecode.UICatalog',
},
}
'sessionId': '1234567890',
'capabilities': {
'device': 'iphone',
'browserName': 'UICatalog',
'sdkVersion': '11.4',
'CFBundleIdentifier': 'com.example.apple-samplecode.UICatalog',
},
}
)

Expand All @@ -132,15 +127,13 @@ def ios_w3c_driver_with_extensions(extensions) -> 'WebDriver':

response_body_json = json.dumps(
{
'value': {
'sessionId': '1234567890',
'capabilities': {
'device': 'iphone',
'browserName': 'UICatalog',
'sdkVersion': '11.4',
'CFBundleIdentifier': 'com.example.apple-samplecode.UICatalog',
},
}
'sessionId': '1234567890',
'capabilities': {
'device': 'iphone',
'browserName': 'UICatalog',
'sdkVersion': '11.4',
'CFBundleIdentifier': 'com.example.apple-samplecode.UICatalog',
},
}
)

Expand Down
72 changes: 33 additions & 39 deletions test/unit/webdriver/webdriver_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def test_create_session(self):
httpretty.register_uri(
httpretty.POST,
f'{SERVER_URL_BASE}/session',
body='{ "value": { "sessionId": "session-id", "capabilities": {"deviceName": "Android Emulator"}}}',
body='{ "value": {"sessionId": "session-id", "capabilities": {"deviceName": "Android Emulator"}} }',
)

desired_caps = {
Expand Down Expand Up @@ -71,7 +71,7 @@ def test_create_session_change_session_id(self):
httpretty.register_uri(
httpretty.POST,
f'{SERVER_URL_BASE}/session',
body='{ "value": { "sessionId": "session-id", "capabilities": {"deviceName": "Android Emulator"}}}',
body='{ "sessionId": "session-id", "capabilities": {"deviceName": "Android Emulator"} }',
)

httpretty.register_uri(
Expand Down Expand Up @@ -100,16 +100,14 @@ def test_create_session_register_uridirect(self):
f'{SERVER_URL_BASE}/session',
body=json.dumps(
{
'value': {
'sessionId': 'session-id',
'capabilities': {
'deviceName': 'Android Emulator',
'directConnectProtocol': 'http',
'directConnectHost': 'localhost2',
'directConnectPort': 4800,
'directConnectPath': '/special/path/wd/hub',
},
}
'sessionId': 'session-id',
'capabilities': {
'deviceName': 'Android Emulator',
'directConnectProtocol': 'http',
'directConnectHost': 'localhost2',
'directConnectPort': 4800,
'directConnectPath': '/special/path/wd/hub',
},
}
),
)
Expand Down Expand Up @@ -142,15 +140,13 @@ def test_create_session_register_uridirect_no_direct_connect_path(self):
f'{SERVER_URL_BASE}/session',
body=json.dumps(
{
'value': {
'sessionId': 'session-id',
'capabilities': {
'deviceName': 'Android Emulator',
'directConnectProtocol': 'http',
'directConnectHost': 'localhost2',
'directConnectPort': 4800,
},
}
'sessionId': 'session-id',
'capabilities': {
'deviceName': 'Android Emulator',
'directConnectProtocol': 'http',
'directConnectHost': 'localhost2',
'directConnectPort': 4800,
},
}
),
)
Expand Down Expand Up @@ -327,29 +323,27 @@ class TestSubModuleWebDriver(object):
def android_w3c_driver(self, driver_class):
response_body_json = json.dumps(
{
'value': {
'sessionId': '1234567890',
'capabilities': {
'platform': 'LINUX',
'desired': {
'platformName': 'Android',
'automationName': 'uiautomator2',
'platformVersion': '7.1.1',
'deviceName': 'Android Emulator',
'app': '/test/apps/ApiDemos-debug.apk',
},
'sessionId': '1234567890',
'capabilities': {
'platform': 'LINUX',
'desired': {
'platformName': 'Android',
'automationName': 'uiautomator2',
'platformVersion': '7.1.1',
'deviceName': 'emulator-5554',
'deviceName': 'Android Emulator',
'app': '/test/apps/ApiDemos-debug.apk',
'deviceUDID': 'emulator-5554',
'appPackage': 'io.appium.android.apis',
'appWaitPackage': 'io.appium.android.apis',
'appActivity': 'io.appium.android.apis.ApiDemos',
'appWaitActivity': 'io.appium.android.apis.ApiDemos',
},
}
'platformName': 'Android',
'automationName': 'uiautomator2',
'platformVersion': '7.1.1',
'deviceName': 'emulator-5554',
'app': '/test/apps/ApiDemos-debug.apk',
'deviceUDID': 'emulator-5554',
'appPackage': 'io.appium.android.apis',
'appWaitPackage': 'io.appium.android.apis',
'appActivity': 'io.appium.android.apis.ApiDemos',
'appWaitActivity': 'io.appium.android.apis.ApiDemos',
},
}
)

Expand Down