microsoft / WinAppDriver

Windows Application Driver
MIT License
3.66k stars 1.4k forks source link

Bad capabilities. Specify either app or appTopLevelWindow to create a session on Python #1848

Open sarthakmahapatra9 opened 1 year ago

sarthakmahapatra9 commented 1 year ago

I am using the following code on WAD using Python. But it is failing with the message "Bad capabilities. Specify either app or appTopLevelWindow to create a session" desired_caps = dict() desired_caps["app"] = "Root" self.driver = webdriver.Remote(command_executor='http://127.0.0.1:4723', desired_capabilities=desired_caps)

appium-python-client version = 2.7.1 Selenium version = 4.7.2

But it works only if appium version is 0.5 and selenium version is 3.141

How do we add "Root" on the latest versions? I do not want to specify it to 1 particular app.

sarthakmahapatra9 commented 1 year ago

Pasting the WinAppDriver logs

POST /session HTTP/1.1
Accept: application/json
Accept-Encoding: identity
Connection: keep-alive
Content-Length: 77
Content-Type: application/json;charset=UTF-8
Host: 127.0.0.1:4723
User-Agent: appium/python 2.7.1 (selenium/4.7.2 (python windows))
X-Idempotency-Key: 594a40b0-8bc3-427b-849c-800c357abf62

{"capabilities": {"firstMatch": [{}], "alwaysMatch": {"appium:app": "Root"}}}
HTTP/1.1 400 Bad Request
Content-Length: 141
Content-Type: application/json

{"status":100,"value":{"error":"invalid argument","message":"Bad capabilities. Specify either app or appTopLevelWindow to create a session"}}`
kzO8Xekb commented 1 year ago

Please note that I am not using Appium and Python, so my answer may be off the mark.

From the WinAppDriver (WAD) logs, it seems that your program did not send the JSON parameter "desiredCapabilities", which must be sent to the WAD when creating a new session.

The JSON object that your program sent to the WAD is as follows.

{"capabilities": {"firstMatch": [{}], "alwaysMatch": {"appium:app": "Root"}}}

The parameter of the JSON object your program is sending is "capabilities". It appears to be an invalid JSON object.

For reference, here is the "desiredCapabilities" in Notepad {"desiredCapabilities":{"app": "C:/Windows/System32/notepad.exe", "deviceName": "WindowsPC", "platformName": "Windows"}}

Translated with www.DeepL.com/Translator (free version)

sarthakmahapatra9 commented 1 year ago

But I am sending the capabilities as desired capabilities only?

desired_caps = dict()
desired_caps["app"] = "Root"
self.driver = webdriver.Remote(command_executor='http://127.0.0.1:4723/', desired_capabilities=desired_caps)
kzO8Xekb commented 1 year ago

The conclusion is that "capabilities" is invalid.

The document WinAppDriver/Tests/WebDriverAPI/README.md says

These tests are written to verify each API endpoint behavior and error values as specified in JSON Wire Protocol document.

Check the JSON Wire Protocol specification that this document refers to.

/session

POST /session

    Create a new session. The server should attempt to create a session that most closely matches the desired and required capabilities. Required capabilities have higher priority than desired capabilities and must be set for the session to be created.

    JSON Parameters:
        desiredCapabilities - {object} An object describing the session's [desired capabilities](https://www.selenium.dev/documentation/legacy/json_wire_protocol/#Desired_Capabilities.md).
        requiredCapabilities - {object} An object describing the session's [required capabilities](https://www.selenium.dev/documentation/legacy/json_wire_protocol/#Desired_Capabilities.md) (Optional).

    Returns:
        {object} An object describing the session's [capabilities](https://www.selenium.dev/documentation/legacy/json_wire_protocol/#Actual_Capabilities.md).

    Potential Errors:
        SessionNotCreatedException - If a required capability could not be set.

You will see that "desiredCapabilities" and "requiredCapabilities" are listed in the JSON parameters. However, you will find that the "capabilities" sent by your program to the WinAppDriver server are not listed.

What response should the server give in this case? According to the specification, the server should respond with a "400 Bad Request".

The results of an experiment to check whether this explanation is correct are shown below.

========================================== POST /session HTTP/1.1 Accept: application/json, image/png Accept-Type: application/json, image/png Connection: Keep-Alive Content-Length: 88 Content-Type: application/json; charset=UTF-8 Host: localhost:4723 User-Agent: Dexador/0.9.15 (SBCL 2.2.4); Win32; 10.0.22000

{"desiredCapabilities":{"app": "Root", "deviceName": "WindowsPC", "platformName": "Windows"}} HTTP/1.1 200 OK Content-Length: 111 Content-Type: application/json

{"sessionId": "2B0F6EA1-D64C-4512-A8EE-E1F65B4F1FB9", "status":0, "value":{"app": "Root", "platformName": "Windows"}}

========================================== POST /session HTTP/1.1 Accept: application/json, image/png Accept-Type: application/json, image/png Connection: Keep-Alive Content-Length: 81 Content-Type: application/json; charset=UTF-8 Host: localhost:4723 User-Agent: Dexador/0.9.15 (SBCL 2.2.4); Win32; 10.0.22000

{"capabilities":{"app": "Root", "deviceName": "WindowsPC", "platformName": "Windows"}} HTTP/1.1 400 Bad Request Content-Length: 141 Content-Type: application/json

{"status":100, "value":{"error": "invalid argument", "message": "Bad capabilities. Specify either app or appTopLevelWindow to create a session"}}

As you can see, it returns an error when requesting with "capabilities".

[Two lines here were deleted because they were inaccurate.] Thanks anunay1!

Translated with www.DeepL.com/Translator (free version)

kzO8Xekb commented 1 year ago

Sorry to repeat myself, but I don't know Python.

I wish I could answer how to rewrite the code, but I cannot comment or advise on Python coding.

sorry. rewrite comment.

anunay1 commented 1 year ago

WAD will not work with the latest version of appium as it is not W3C compliant yet.

bp24acharya commented 1 year ago

@sarthakmahapatra9 could you fix the issue? I am getting the same error, the only difference is I am using Java

Shakevg commented 1 year ago

sarthakmahapatra9, bp24acharya You should rollback Selenium to version 3.14 and Appium to 7.6 https://stackoverflow.com/questions/74632066/appium-winappdriver-and-selenium-4

fbwang commented 1 year ago

@kzO8Xekb is right. This issue is because:

  1. Appium-python-client add a prefix before 'app'/'deviceName'
  2. Appium-python-client removed desiredCapabilities. To fix this you need:
  3. In Appium-Python-Client-2.8.1\appium\options\common\base.py either remove the prefix in 'as_w3c' function or add 'app'/'deviceName' to W3C_CAPABILITY_NAMES dist.
  4. In Appium-Python-Client-2.8.1\appium\options\common\base.py change the return value something like this:
        # return {'capabilities': {'firstMatch': [{}], 'alwaysMatch': processed_caps}}
        return {'desiredCapabilities':processed_caps,'capabilities': {'firstMatch': [{}]} }
bp24acharya commented 1 year ago

Hi, Thanks. It is still not running. Do you have time to see my code please?

On Sun, Mar 12, 2023 at 3:07 AM fbwang @.***> wrote:

@kzO8Xekb https://github.com/kzO8Xekb is right. This issue is because:

  1. Appium-python-client add a prefix before 'app'/'deviceName'
  2. Appium-python-client removed desiredCapabilities. To fix this you need:
  3. In Appium-Python-Client-2.8.1\appium\options\common\base.py either remove the prefix in 'as_w3c' function or add 'app'/'deviceName' to W3C_CAPABILITY_NAMES dist.
  4. In Appium-Python-Client-2.8.1\appium\options\common\base.py change the return value something like this:

    # return {'capabilities': {'firstMatch': [{}], 'alwaysMatch': processed_caps}}
    return {'desiredCapabilities':processed_caps,'capabilities': {'firstMatch': [{}]} }

— Reply to this email directly, view it on GitHub https://github.com/microsoft/WinAppDriver/issues/1848#issuecomment-1465079687, or unsubscribe https://github.com/notifications/unsubscribe-auth/AQNDXVHLPMACPDGOH2U2Z7TW3U4YDANCNFSM6AAAAAATY5XF5U . You are receiving this because you commented.Message ID: @.***>

-- Thanks and Regards Prarthana Mehta Acharya Email: @.***

amitraj012 commented 1 year ago

@kzO8Xekb is right. This issue is because:

  1. Appium-python-client add a prefix before 'app'/'deviceName'
  2. Appium-python-client removed desiredCapabilities. To fix this you need:
  3. In Appium-Python-Client-2.8.1\appium\options\common\base.py either remove the prefix in 'as_w3c' function or add 'app'/'deviceName' to W3C_CAPABILITY_NAMES dist.
  4. In Appium-Python-Client-2.8.1\appium\options\common\base.py change the return value something like this:
        # return {'capabilities': {'firstMatch': [{}], 'alwaysMatch': processed_caps}}
        return {'desiredCapabilities':processed_caps,'capabilities': {'firstMatch': [{}]} }

I tried your workaround, but it's still not working for me, please advise image

image

Willikin commented 1 year ago

@kzO8Xekb is right. This issue is because:

  1. Appium-python-client add a prefix before 'app'/'deviceName'
  2. Appium-python-client removed desiredCapabilities. To fix this you need:
  3. In Appium-Python-Client-2.8.1\appium\options\common\base.py either remove the prefix in 'as_w3c' function or add 'app'/'deviceName' to W3C_CAPABILITY_NAMES dist.
  4. In Appium-Python-Client-2.8.1\appium\options\common\base.py change the return value something like this:
        # return {'capabilities': {'firstMatch': [{}], 'alwaysMatch': processed_caps}}
        return {'desiredCapabilities':processed_caps,'capabilities': {'firstMatch': [{}]} }

I tried your workaround, but it's still not working for me, please advise image

image

also need to set APPIUM_PREFIX = '' in base.py