简体   繁体   中英

Testing HTML5 File Upload with Capybara/Selenium Webdriver - Ruby

I have a simple modal that appears in which the user is shown the browse button to add the file to upload. Due to an unknown issue, be it the fact its an HTML5 file input therefore the browser adds its own functions to it, this has become a pain to test.

On my page I have:

       <input type="file" id="photo_upload">

Capybara offers a solution out of the box which is:

       attach_file <<upload_file_id>>, <<file_path>>

This behind the scenes executes a send_keys command to push the file_path into the path container for this input, however this simply did not work with my setup. I am running Firefox 25.0.1 on Windows 8. I tried both a relative path and a full path to this file, with forward and backslash combinations.

When I mean it did not work, I mean when my ajax script executes from clicking the button 'upload' next to it, it does not send any file object in the params.

I even tried to use capybara to send the file path directly:

       find_field(<<upload_file_id>>).native.send_keys(<<file_path>>)

Next up, was to attempt to use selenium to push it in using:

       element = driver.find_element(:id, <<upload_file_id>>)
       element.send_keys <<file_path>>

Then I tried executing script to ensure the element was visible, and then setting it:

      element = page.execute_script(
          "document.getElementById('#{<<upload_file_id>>}').style.visibility = 'visible';                  
           document.getElementById('#{<<upload_file_id>>}').style.height = '20px'; 
           document.getElementById('#{<<upload_file_id>>}').style.width = '60px';  
           document.getElementById('#{<<upload_file_id>>}').style.opacity = 1; return 
           document.getElementById('#{<<upload_file_id>>}')")
     find_field(field_locator).native.send_keys(<<file_path>>)

This didn't work either. Now I am completely stuck. All the help on here and google points to using the above, but it just simply does not work for my setup.

My options as far as I can see it are to use a windows automation script and jump out of capybara, run the script, and then continue, or to directly call the upload url either from capybara using a post or calling the js ajax that currently does it.

So I have solved it, and its not too ugly. I used the automation route via AutoIT. The bundle you download with AutoIT includes a script to exe converter and using the below script (I can not take credit for the script) I created an exe:

Local Const $dialogTitle = $CmdLine[2]
Local Const $timeout = 5

Local $windowFound = WinWait($dialogTitle, "", $timeout)

$windowFound = WinWait($dialogTitle, "", $timeout)
Local $windowHandle

If $windowFound Then
    $windowHandle = WinGetHandle("[LAST]")
    WinActivate($windowHandle)

    ControlSetText($windowHandle, "", "[CLASS:Edit; INSTANCE:1]", $CmdLine[1])
    ControlClick($windowHandle, "", "[CLASS:Button; TEXT:&Open]")        
Else
    MsgBox(0, "", "Could not find window.")
    Exit 1
EndIf

In my capybara script, I merely run:

find_field(<<upload_file_id>>).click
system("<<full_path>>\\file_upload.exe \"#{<<file_path>>}\" \"File Upload\"")

and it works perfectly! In fact, I think I prefer the fact it exactly mimics what a user would be doing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM