Testing HTML5 File Upload with Capybara/Selenium Webdriver - Ruby
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.
Capybara returns Argument error when attach the file
When using the block version of attach_file Capybara attaches a listener for clicks on <input type="file">
elements and uses that to determine which input you want a file attached to. Since it's not finding it either it's not triggering the click, or the way your code is structured is hiding the click from Capybara. First I'd ask why you're using all
and the element
selector type to find the button and instead suggest (assuming browser is the Capybara session??)
browser.attach_file($private_key_path) do
browser.find('material-button', text: 'Upload generated ZIP').click
end
It's tough to say if that's correct because you don't actually show the HTML for a button with that text in your question though. If that still doesn't work then you're going to need to actually locate the file input element and use the non-block version of attach_file. Something like
attach_file($private_key_path, make_visible: true)
or by first finding the file input yourself
browser.find('input[type="file"]', visible: false).attach_file($private_key_path, make_visible: true)
Again it's hard to say for sure since your HTML doesn't appear to actually show the button you're trying to click.
Capybara doesn't wait till the end of file upload
So, the turnaround was maybe not the most professional but at least it worked and I can automate some things now.
Basically, I used has_button?
to make my script wait till the APK file will be uploaded. 200sec is enough for file upload (statistically).
In the end, the script makes a pause but I decided to add sleep 3
in the end just to be on the safe side.
Here is the function which uploads APK for me. Maybe someone will need it
def create_release
puts('Create release and upload APK')
browser.find(:element, 'div', role: 'menuitem', text: 'Production').click
create_release_btn = browser.all(:button, text: 'Create new release')
create_release_btn[0].click
#OPT out
browser.click_button('Manage preferences', wait: 200)
sleep 2
browser.choose('Opt out of app signing by Google Play')
browser.click_button('Update', wait: 100)
sleep 3
op_out_btn = browser.all(:button, text: 'Opt out', wait: 500)
op_out_btn[0].click
sleep 4
#File upload part and saving
upload_btn = browser.all(:element, 'span', text: 'Upload')
browser.attach_file($app_path) do
upload_btn[0].click
end
save_btn = browser.all(:element, 'material-button', text: 'Save', disabled: false, wait: 200)
browser.has_button?(save_btn, disabled: false, wait: 200)
button_test = browser.all(:button, text: 'Save', wait: 100)
button_test[0].click
sleep 3
end
capybara poltergeist cant upload file
File inputs are often hidden for styling reasons, which makes them non-interactable. Because of that capybara'sattach_file
has an option to make it easier to temporarily make the file input visible/interactable
page.attach_file field, file_path, make_visible: true
That will temporarily apply CSS { opacity: 1, display: 'block', visibility: 'visible' } to the file input element. If that CSS won't make the input visible you can set make_visible
to a hash that will rather than true
Related Topics
How to Ignore File Types in a Web Crawler
Uri::Invalidurierror: Bad Uri(Is Not Uri) Testing Rails Controllers
Expressing Conditional Haml Possibly with Ternary Operator
Why Does Single '=' Work in 'If' Statement
Rails Cannot Find Model with Same Name as Ruby Class
Rewrite Template.Js.Erb into Template.Js.Slim
Cucumber: Automatic Step File Creation
Undefined Method 'Has_Attached_File' with Paperclip 2.3.8 Gem for Rails 2 Using Ruby 1.8.7
Ruby, Rails Gem Install Error - Error: While Executing Gem ... (Encoding::Undefinedconversionerror)
Return Values Were Not Extracted in Ruby
How to Access Text Field in an Iframe
What Does "File.Sync = True" Do
How to Recursively Flatten a Yaml File into a JSON Object Where Keys Are Dot Separated Strings
How to Effectively Force Minitest to Run My Tests in Order
Nameerror: Undefined - Have Parsing Rules for Local Variables Changed in Ruby 2.1.2
Rails Syntax Error: Unexpected Keyword_Ensure, Expecting Keyword_End