pythonseleniumsafariselenium-gridsafaridriver

How to upload a file through the input tag using Selenium Safari and Python


I have a selenium script that is working for chrome and firefox. I need to add support for safari (13). This is selenium grid working through LambdaTest.

I'm getting stuck with safari file uploads. Here is the code that works for other browsers:

file_input = self.driver1.find_elements_by_css_selector("input[type='file']")[0]
time.sleep(2)
file_input.send_keys(DIR_PATH + r"/snap1.jpg")
time.sleep(2

With safari I get this error message:

selenium.common.exceptions.InvalidArgumentException: Message: One or more files could not be selected.

This error stems from this the send_keys() line. DIR_PATH is defined as os.path.dirname(os.path.realpath(__file__)) and snap1.jpg is a jpg file living in the same directory as my selenium test.

I haven't been able to find anything about this specific error. Any advice?


Solution

  • This error message...

    selenium.common.exceptions.InvalidArgumentException: Message: One or more files could not be selected.
    

    ...implies that the SafariDriver was unable to send the character sequence to the <input> field.


    Deep Dive

    @jmleyba in his comment clearly mentioned:

    The SafariDriver is implemented in JS and does not have the privileges necessary to manipulate a element. Therefore, the SafariDriver does not support file uploads.

    @jmleyba further in another comment added:

    you cannot set the value of an <input type="file"> element (the path of the file that should be uploaded by the browser). The behavior is currently undefined. The SafariDriver will probably generate a series of key events on the element with no discernable effect. We should probably generate an error when the target is a file element.

    However @mangaroo suggested a workaround as:

    I guess workaround for those that really want to do file upload for SafariDriver would be not to do it natively via SafariDriver but by using external code libraries to perform the upload via HTTP/HTTPS (POST) requests (combining any other form data in addition to the file being uploaded/sent), then get response and check whether upload succeeded or not, then go back to SafariDriver code and navigate to next page to check upload succeeded or not, and/or to continue from there for the next steps in the automation.

    This approach would be similar to the file download method using HTTP requests externally that has been mentioned in various posts in WebDriver and Selenium user Google groups. Here, it's just the inverse, doing upload instead of download.

    Though if the upload requires a session (cookie), then you can extract Selenium session cookie and use with HTTP request. Or if session is stored with session ID in URL, extract that and pass along with HTTP request.


    Conclusion

    SafariDriver won't support the file upload through <input type="file"> . An alternative would be to use a HTTP/HTTPS method (typically via an HTTP/HTTPS POST request sending the file as the POST body) to upload the file through Safari.