kuzzooroo
kuzzooroo

Reputation: 7408

Simple file upload snippet in Selenium works in Chrome but not Firefox on my Mac

Courtesy of this answer I've got this bit of Selenium working:

import contextlib
from selenium import webdriver

with contextlib.closing(webdriver.Chrome()) as driver:
    driver.get("http://www.bing.com/images")
    driver.find_element_by_id("sbi_t").click()
    element = driver.find_element_by_id("sbi_file_upload")
    element.send_keys("//Loch Ness Monster.jpg")

However, when I switch from webdriver.Chrome() to webdriver.Firefox(), I start getting selenium.common.exceptions.ElementNotVisibleException: Message: Element is not currently visible and so may not be interacted with. My guess is that the error is related to the magic that Selenium performs to work with operating system file upload selector dialogs. I would think that's probably also why my attempts to wait until the element becomes visible aren't working: the "magic" does not involve the element ever becoming visible. Here's what I tried:

# https://stackoverflow.com/a/15142611/2829764, found via https://stackoverflow.com/q/6101461/2829764
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
...
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "sbi_file_upload")))

I'm using Firefox 36.0.1, Selenium 2.45.0, and Python 2.7.9. Incidentally, Selenium had stopped working with Firefox when I updated Firefox to 36.0.1 but I updated my Selenium today and the particular problem I was having went away.

Upvotes: 1

Views: 2230

Answers (4)

user7713236
user7713236

Reputation:

Try This , If is_displayed() method gives an exception

from selenium import  webdriver

def is_Displayed(class_name):
    ele=driver.execute_script("return document.getElementsByClassName('"+class_name+"')[0].style.visibility = 'visible';")
    if ele=="visible":
        return True
    else:
        return False

def test_check_element():
    global driver
    driver=webdriver.Safari()//e.g Firefox() , Chrome()
    driver.maximize_window()
    driver.implicitly_wait(30)
    driver.get("url")
    submitBtn=driver.find_element_by_xpath("//button[@title='Submit']").get_attribute("class")


    if is_Displayed(submitBtn)== True:
        print "Displayed "
    else:
        print "Not Displayed"

Upvotes: 0

gil
gil

Reputation: 21

The solution 'make the element visible in firefox ' was great for me

driver.execute_script('arguments[0].style = ""; 
arguments[0].style.display = "block"; 
arguments[0].style.visibility = "visible";', file_input)

Upvotes: 2

kuzzooroo
kuzzooroo

Reputation: 7408

Lightly modified version of @alexce's answer. It's the only thing I've found that works consistently on my machine.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import selenium

driver = webdriver.Firefox()
driver.get('http://www.bing.com/images')

WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "sbi_t")))
driver.find_element_by_id("sbi_t").click()

try:
    WebDriverWait(driver, 1).until(EC.visibility_of_element_located((By.ID, "sbi_file_upload")))
    raise Exception("This never seems to happen")
except selenium.common.exceptions.TimeoutException:
    pass

button = driver.find_element_by_id('sbi_gh')
driver.execute_script('arguments[0].style.display = "block";', button)
button.click()  # submitting the form, empty file
driver.back()

WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "sbi_t")))
driver.find_element_by_id("sbi_t").click()
file_input = driver.find_element_by_id('sbi_file_upload')
driver.execute_script('arguments[0].style = ""; arguments[0].style.display = "block"; arguments[0].style.visibility = "visible";', file_input)
file_input.send_keys("//Loch Ness Monster.jpg")

Upvotes: 2

alecxe
alecxe

Reputation: 473983

The element you are sending keys to has an opacity value set to 0:

<input id="sbi_file_upload" name="imageBinary" type="file" accept="image/*" style="opacity: 0;">

And Firefox (correctly) thinks the element is invisible:

>>> from selenium import webdriver
>>> driver = webdriver.Firefox()
>>> driver.get("http://www.bing.com/images")
>>> driver.find_element_by_id("sbi_t").click()
>>> element = driver.find_element_by_id("sbi_file_upload")
>>> element.is_displayed()
False

Here are the relevant issues that actually are the reason for the behavior we see:


The solution here would be to make the input visible so that we can send the keys to it. I've found a rather weird way to make the input visible - it involves sending an empty file value first, going back and making the input visible through execute_script(). Hope, you'll make it work without an extra back() step:

>>> driver = webdriver.Firefox()
>>> driver.get('http://www.bing.com/images')
>>> driver.maximize_window()
>>> 
>>> driver.find_element_by_id("sbi_t").click()
>>> 
>>> button = driver.find_element_by_id('sbi_gh')
>>> driver.execute_script('arguments[0].style.display = "block";', button)
>>> button.click()  # submitting the form, empty file
>>> 
>>> driver.back()
>>> driver.find_element_by_id("sbi_t").click()
>>> 
>>> file_input = driver.find_element_by_id('sbi_file_upload')
>>> file_input.is_displayed()
False
>>> 
>>> driver.execute_script('arguments[0].style = ""; arguments[0].style.display = "block"; arguments[0].style.visibility = "visible";', file_input)
>>> 
>>> file_input.is_displayed()
True

And now you can send keys to file input - tested, works for me.

Upvotes: 2

Related Questions