Upload Files With Selenium (Windows Version)

In case when you have basic HTML input for file it’s very easy, just run .find_element_by_id('id_photo').send_keys(<full path to file>). But very often we don’t have such inputs or they are hidden and we cann’t send keys to them. For such cases with using Windows we can do it with help of pywinauto or other automation GUI utilities.

So, if you have open file dialog and run test on windows, I have solution. With help of pywinauto we can put path to file into dialog and click “Open”. To connect pywinauto to browser we should have process id, for Firefox we already have right id in driver instance but if you use Chrome, driver has only pid of browser but you need pid of tab, in my example I have only one tab and in code I just get first child of browser. Also we should do few tries to fill out dialog or run some sleep to wait for dialog will be opened.

Next you can found simple example how to upload file.

#!/usr/bin/python
import psutil
from unittest import TestCase
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from pywinauto.application import Application


class UploadTestCase(TestCase):
    def setUp(self):
        self.browser = webdriver.Chrome()
        self.wait = WebDriverWait(self.browser, 10)

    def tearDown(self):
        self.browser.close()

    def get_pid(self):
        if isinstance(self.browser, webdriver.Chrome):
            process = psutil.Process(self.browser.service.process.pid)
            return process.children()[0].pid              # process id of browser tab
        if isinstance(self.browser, webdriver.Firefox):
            return self.browser.service.process.pid       # process id of browser

        assert Exception('driver does not supported')

    def upload_file(self, filename):
        path = os.path.join(
            os.path.realpath('.'),
            'fixtures',
            filename
        )
        assert os.path.exists(path)

        for i in range(10):
            app = Application()
            app.connect(process=self.get_pid())  # connect to browser
            dialog = app.top_window_()           # get active top window (Open dialog)
            if not dialog.Edit.Exists():         # check if Edit field is exists
                time.sleep(1)                    # if no do again in 1 second (waiting for dialog after click)
                continue
            dialog.Edit.TypeKeys('"{}"'.format(path))   # put file path
            dialog['&OpenButton'].Click()               # click Open button

            return

        raise Exception('"Open File" dialog not found')

    def test_upload_small_logo(self):
        el_logo_upload = self.wait.until(
            EC.presence_of_element_located(
                (By.NAME, upload-logo')
            )
        )

        el_logo_upload.click()
        self.upload_file('logo_small.png')

        # checking