'Trying to automate a file upload with chromedriver but type="file" doesn't exist till I click

I apologize in advance if this is to detailed, I really tried my best to make my problem clear.

I need to upload a bunch of jpg files. Unfortunately if I don't automate the process it means days of clicking.

I'm using Python, Jupyter Notebook and chromebrowser to login and navigate through the interface, to where I want to upload the jpg. This is the stuff in my header.

from   selenium import webdriver
from   selenium.common.exceptions import TimeoutException
import time
import datetime
import csv
import getpass
import os
import win32com.client
import pandas as pd
from selenium.webdriver.common.keys import Keys

Mostly I navigate by using some form of id, class, or xpath

element = driver.find_element_by_xpath("copy_of_the_xpath")
element.send_keys("password")

Or

element = driver.find_element_by_xpath("copy_of_the_xpath")
element.click()

So I navigate to the "selectFileBtn" which allows me to select a jpg for uploading. If I was doing this manually, I'd click this button, it would open a new window so I can select the file I want to. I would then have to click second button to confirm the upload "commitFileBtn"

<div style="float:right;">
<input type="button" name="" value="Select Material" id="selectFileBtn" class="button_basic">
<input type="button" name="" value="Upload" id="commitFileBtn" class="button_basic button_right">
</div>

Now I don't want to click the "selectFileBtn". I just want to give it the file. Normally I would just send the file using.

element = driver.find_element_by_xpath("xpath_to_selectFileBtn")
element.send_keys("file_to_be_uploaded")

But unfortunately "selectFileBtn" is type=button and I need type=file to send something. So I was really lost. Then I realized if I click the button the elements change from

<div style="float:right;">
<input type="button" name="" value="Select Material" id="selectFileBtn" class="button_basic">
<input type="button" name="" value="Upload" id="commitFileBtn" class="button_basic button_right">
</div>

to

<div style="float:right;">
<input type="button" name="" value="Select Material" id="selectFileBtn" class="button_basic">
<input type="file" style="display:none;" multiple="" accept=".jpg">
<input type="button" name="" value="Upload" id="commitFileBtn" class="button_basic button_right">
</div>

And if I then send my file to the xpath

element = driver.find_element_by_xpath('//*[@id="uploadCond"]/div/input[2]')
element.send_keys("file_to_be_uploaded")

of this element

<input type="file" style="display:none;" multiple="" accept=".jpg">

the whole thing works as intended. Now I have a different problem: I can not make

<input type="file" style="display:none;" multiple="" accept=".jpg">

available through anything but clicking on it. And if I use the command

element.click()

then it takes 60+ seconds to open the window because some javascript black magic is happening and that is unfortunately to long. If I click it manually it almost instantly opens.

So I tried to create the node myself:

def create_material_node():
        execu='''
        var x = document.createElement("INPUT");
        x.setAttribute("type", "file");
        x.setAttribute("style", "display:none;");
        x.setAttribute("multiple", "");
        x.setAttribute("accept", ".jpg");
        var element = document.getElementById("uploadCond").getElementsByTagName("div")[0];    
        element.insertBefore(x, element.children[1]);
        '''
        browser.execute_script(execu)

And to clone the node I wanted to send to:

def clone_node():
    clone='''
    var menu = document.getElementById("uploadCond").getElementsByTagName("div")[0].getElementsByTagName("input")[1];
    var clonedMenu = menu.cloneNode();
    var element = document.getElementById("uploadCond").getElementsByTagName("div")[0];
    element.insertBefore(clonedMenu, element.children[1]);
    '''
    browser.execute_script(clone)

But both the creation and the clone couldn't upload the jpg I sent.

One thing I noticed was that the clone was missing an event listener called "change". I looked at change source panel but it was in Jquery and Javascript and I don't even know were to begin. I'm just stuck at this point. Does anyone know how I can automate uploading these files?

("#selectFileBtn").click(function(){
                var extName = "";
                if (self.getExtName) {
                    extName = self.getExtName();
                }

                $(this).parent().remove("input:file");
                $(this).after("<input type='file' style='display:none;' multiple />");
                $(this).next("input:file").attr("accept", extName).change(function(evt){
                    self.doUpload(evt.target);
                }).click();
            });


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source