have trouble with using capybara-webkit attach_file upload an image - ruby-on-rails

I want to test the function to add an image to the application. How can I do this. attach_file method is not work. I don't know why.
html:
<form id="edit_user_5577b0c4a851ac600c000002" class="form-horizontal user-settings" method="post" enctype="multipart/form-data" action="/tardis54" accept-charset="UTF-8">
<div id="upload-avatar" class="control-group">
::before
<label class="control-label" for="user_avatar">
Setting avatar
</label>
<div class="controls">
<div class="form-fileupload">
<div class="image-preview">
<img class="gravatar img-circle" width="60" height="60" src="http://gravatar.com/avatar/7046a07b25397e4a0c838a47c88d8742?default=identicon&secure=false&size=60" data-retina-url="http://gravatar.com/avatar/7046a07b25397e4a0c838a47c88d8742?default=identicon&secure=false&size=120" alt="tardis54"></img>
</div>
<span class="btn btn-fileinput btn-default">
<span>
Choose file ...
</span>
<input id="user_avatar" class="input-file" type="file" name="user[avatar]"></input>
</span>
</div>
</div>
</div>
<div class="form-actions pull-right">
<input class="btn btn-large btn-primary" type="submit" value="Update" name="commit"></input>
</div>
</form>
test code:
scenario "upload a custom avatar" do
attach_file("user[avatar]", Rails.root + "temp4.png")
end
error log:
Failure/Error: attach_file("user[avatar]", Rails.root + "temp4.png")
Capybara::Webkit::ClickFailed:
Failed to click element /html/body/div[#id='content']/div/div/div/div/div/div[2]/form[#id='edit_user_5580e19da851ac6a51000002']/div[#id='upload-avatar']/div/div/span/input[#id='user_avatar']
because of overlapping element /html/body/div[#id='content']/div/div/div/div/div at position 740, 627;

It looks like you're using CSS to overlay another element on top of the HTML input. Some people do this because it's difficult to style HTML file inputs directly. However, doing so breaks capybara-webkit, because it needs to click on the actual HTML input field and the styled element is positioned on top of it.
This is being discussed in a GitHub issue.
You can work around it in the test by using execute_script to hide the overlay element, and then attempting to upload the file.

I find a way to solve this problem.
script = "$('#user_avatar').css({opacity: 100, display: 'block', position: 'relative', left: ''});"
page.execute_script(script)

I could assume that input[type=file] is not visible, thus you need initially make it visible f.e. execute javascript $("input[type=file]").show() and than attach file

Here's my implementation of #tardis answer (which itself is an implementation of #joe-ferris' suggestion). I put it as an answer to be able to use code formatting.
# spec/support/file_uploads.rb
module FileUploads
# Enables file uploads by capybara-webkit on pages that
# style file their input fields
def attach_file_styled_input(element_id, file)
page.execute_script("$('##{element_id}')" +
".css({opacity: 100, display: 'block', position: 'relative', left: ''});")
attach_file element_id, file
end
end
Don't forget to include this support module in spec/rails_helper.rb:
config.include FileUploads
Then use it in your feature spec like this (not spectacular):
attach_file_styled_input 'my_input_id', 'my_file'

Related

Bootstrap inline form buttons

As shown in the image, my buttons are not inline with eachother and the cancel button is far bigger than it should be.
This is the code I'm currently using:
<div class="form-group row">
<div class="col-sm-offset-2 col-sm-10">
<%= button_tag t('btn.save'), class: 'btn btn-brand-color', type: 'submit' %>
<%= link_to t('btn.cancel'), :back, class: 'btn btn-default' %>
</div>
</div>
What I want is to have the two buttons next to each other preferably by using already existing bootstrap classes.
As per comment - you have a link (a) declaration which is set to 100%.
tip -- might be easiest to use the browser inspector to find out which class and in which css file are overriding your intention.
For others in the future: If there is any doubt about whether a class is vanilla bootstrap, or something you've inadvertently overriding a class you hadn't intended to, you can view bootstrap's native behavior by inspecting the html row or element, right clicking - then click on Copy as HTML
In this questions example that output would be
<div class="form-group row">
<div class="col-sm-offset-2 col-sm-10">
<button name="button" type="submit" class="btn btn-brand-color"><span class="translation_missing" title="translation missing: en.btn.save">Save</span></button>
<a class="btn btn-default" href="javascript:history.back()"><span class="translation_missing" title="translation missing: en.btn.cancel">Cancel</span></a>
</div>
</div>
Paste that into http://www.bootply.com/new and click Run -- it's a good indicator of style interference (also Bootply lets you change versions of bootstrap to match your own.
I never used ruby-on-rails before. But if you get this, maybe you should create a new CSS class and include display: inline-block on the button & make sure the button with are not set width: 100%.

Bootstrap multi-line form-controls for a span

Having a problem displaying text when longer than one line in a span with a bootstrap form-control class (see images below). Looking for a solution in Bootstrap which would wrap the text in a box but keep the look even when overflowed on to the next line.
HTML Code
View Result
EDIT Complete Code:
#*Kpi Selection/Display*#
<div class="form-group">
<label class="col-lg-2 control-label">KPI Selection</label>
<div class="col-lg-10">
<span id="KpiCode-display" class="form-control">
#Html.DisplayFor(model => model.WorkOrder.KpiDetails.DetailsKpi.KpiFull)
</span>
<span id="KpiSelection-edit" style="display: none">
</span>
</div>
</div>
The form-control class needs to be applied to an input/select. The style it applies doesn't work with something like a span. If you're looking for a static text control, the class you should be applying is form-control-static. See: http://getbootstrap.com/css/#forms-controls-static.

How can I use Bootstrap button addons in my MVC view

I'm having difficulty getting Bootstrap's button addons to work in my MVC view. I'm using the latest NuGet version of ASP.NET MVC (5.1 rc1) and Bootstrap (3.03).
I have the following in my view (now that I've pared it back to just hand-coded HTML rather than using Html.EditorFor(), in an attempt to getting it to work):
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true)
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<input type="text" class="form-control" />
<span class="input-group-btn">
<button class="btn btn-default" type="button">Go!</button>
</span>
</div>
</div>
<div class="col-lg-6">
</div>
</div>
This generates the following HTML:
<form action="xxx" method="post">
<input name="__RequestVerificationToken" type="hidden" value="T3k..." />
<div class="form-horizontal">
<div class="row">
<div class="col-lg-6">
<div class="input-group">
<input type="text" class="form-control" />
<span class="input-group-btn">
<button class="btn btn-default" type="button">Go!</button>
</span>
</div>
</div>
<div class="col-lg-6">
</div>
</div>
</div>
</form>
The problem is that, when this is displayed in the browser (Chrome 32 / IE 11), there's a big gap between the input box and the button. Like this:
If I reduce the size of the div surrounding the input-group div to col-lg-3 or smaller, it's fine. But anything larger than that leaves a gap.
It's as though there's a maximum size on the input - and indeed, all my inputs do seem to be smaller their container div...
What could be causing this?
The default Site.css stylesheet that comes with a new MVC 5 project has a rule that limits the max-width of inputs. What you're getting is the result of the control spanning the full available width like it's supposed to, but then the input, itself, is being constrained to a defined width. Just comment out that piece of the stylesheet and everything will work as it should.
/* Set width on the form input elements since they're 100% wide by default */
input,
select,
textarea {
max-width: 280px;
}
It's a pretty egregious shortcut the team seems to have taken in order to quickly build the sample site.

Styling file upload button for simple_form_for with Bootstrap in Rails 3

Using simple_form_for, Bootstrap and Rails 3. In a form:
<%= f.input :upload, label: 'PDF file:' , input_html: {accept: ('application/pdf') } %>
I don't know how I'd style this so that the "choose file" button can have a different class ('btn btn-primary').
Additionally, when using with Bootstrap at least, its severely misaligned by default. See attached image.
Finally, how do I redefine the text from "No file chosen" to "Chose file" when there isn't one added yet, and show the file name when there is one.
This is how I do it:
In the view add your form file field and hide it
Add a styled additional field just to display the file name
Add a button to trigger the file browse dialog
<div class="control-group">
<div class="attach-set">
<%= f.input :real_file, input_html: { hidden: true }, label: 'Upload Attachment' %>
<div class="input-append">
<input id="file-display" class="input-large uneditable-input" type="text">
<a id="upload-btn" class="btn"><i class="icon-upload-alt"></i> Browse</a>
</div>
</div> <!-- /attach-set -->
</div> <!-- /control-group -->
In your JS (Coffee w/ jQuery shown), pass the click from the display button onto the real file input and when they select a file drop the file name in the display text field (I drop the path so that I don't see C:\FakePath....)
$(document).ready ->
# ------------------------------------------------------
# pretty-fy the upload field
# ------------------------------------------------------
$realInputField = $('#real_file')
# drop just the filename in the display field
$realInputField.change ->
$('#file-display').val $(#).val().replace(/^.*[\\\/]/, '')
# trigger the real input field click to bring up the file selection dialog
$('#upload-btn').click ->
$realInputField.click()
This worked great for me and only requires HTML
<label class="btn btn-primary">
Add a file!
<span style="display:none;">
<%= f.file_field :image, required: true, multiple: true, name: 'picture' %>
</span>
</label>
I ran across and am using Jasny's extension to Bootstrap 3. It seems to work well so far.
No JS required, just plain css
scss
.fileinput-button {
position: relative;
overflow: hidden;
float: left;
margin-right: 4px;
width: 110px;
height: 32px;
input{
opacity: 0;
filter: alpha(opacity=0);
transform: translate(-300px, 0) scale(4);
direction: ltr;
cursor: pointer;
}
}
html / slim
span class="btn btn-success fileinput-button"
i.fa.fa-pencil
span
| Select File
= f.file_field :cover_ar
I recommend using compass for cross browser compatibility
As #rafaelfranca said you can't style file input but you can add your own button which will be clicking your hidden original button. See example here http://jsfiddle.net/rUdf2/6/
Every Browser has a different type of file input field button and this makes it a pain. You can play a little with css. This has given me a basic styling with JS without the annoying "No file chosen" text in chrome and Safary:
$(document).ready(function() {
$(".your_button").css("width", "80px");
});
Otherwise the best solution is to hide it and show a fake one that intercepts the click:
http://duckranger.com/2012/06/pretty-file-input-field-in-bootstrap/
With respect to the question of how to show that a file has been uploaded, a basic solution with jquery file upload is to detect the upload complete event and replace some of your text with a success message (The exact file name I believe it is not possible to obtain with modern browsers):
$(".your_button").fileupload({
dataType: "json",
done: function(e, data) {
$(".place_for_your_text").text("File uploaded.");
}
});
In summary, a basic solution is to use javascript in your assets to:
Hide the annoying "No file chosen text" with css.
Place your "Chose file" text next to the button and give it a class you can reference.
Replace the text with "File uploaded"
No fancy shiz required:
HTML:
<form method="post" action="/api/admin/image" enctype="multipart/form-data">
<input type="hidden" name="url" value="<%= boxes[i].url %>" />
<input class="image-file-chosen" type="text" />
<br />
<input class="btn image-file-button" value="Choose Image" />
<input class="image-file hide" type="file" name="image"/> <!-- Hidden -->
<br />
<br />
<input class="btn" type="submit" name="image" value="Upload" />
<br />
</form>
JS:
$('.image-file-button').each(function() {
$(this).off('click').on('click', function() {
$(this).siblings('.image-file').trigger('click');
});
});
$('.image-file').each(function() {
$(this).change(function () {
$(this).siblings('.image-file-chosen').val(this.files[0].name);
});
});
CAUTION: The three form elements in question MUST be siblings of each other (.image-file-chosen, .image-file-button, .image-file)
If you are using Bootstrap, Simple Forms, Jasny, and ReFile, this post may be of interest to you refile simple_form undefined method attachment_field
<label class="btn btn-primary"
<%= f.input :upload, label: 'PDF file:',
class:"hidden", input_html: {accept: ('application/pdf') } %>
</label>
Works for me
Using class="hidden"
PS: I'm using Tailwind CSS

Click on element with capybara

I have a yes/no slider on a web page that i need to interact with. I need to click on one of the elements so that the value changes from true to false or false to true. Using the id i can get the value of the element with
find_field('passcode_policies__allow_simple').find('option[selected]').value
But i have tried over and over to simulate a click on this object to change the value and have been unsuccessful.
<div class="control-group">
<select class="toggle" id="passcode_policies__allow_simple" name="passcode_policies[][allow_simple]" style="display: none; " tabindex="-1">
<option value="true" selected="selected">Yes</option>
<option value="false">No</option>
</select>
<div class="ui-switch off" tabindex="0">
<div class="ui-switch-mask">
<div class="ui-switch-master" style="left: -38px; ">
<div class="ui-switch-upper">
<span class="ui-switch-handle" style="left: 33px; "></span>
</div>
<div class="ui-switch-lower">
<div class="ui-switch-labels">
Yes
No
</div>
</div>
</div>
</div>
<div class="ui-switch-middle" style="width: 60px; ">
</div>
</div>
<label class="inline">Allow simple value</label>
<span class="help-block">Permit the use of repeating, ascending, and descending character sequences</span>
</div>
If you're using Selenium, headless webkit or phantomjs (poltergeist gem) you should be able to call the simple
click_link 'Yes'
but if you're just using straight up capybara you will have to interact with the select element with something like
select('Yes', :from => 'passcode_policies__allow_simple')
and you can check the visibility and whatnot with this capybara: page.should have_no_content doesn't work correctly for display:none element
Working solution:
within(:css, '#passcode_policies__allow_simple + .ui-switch') do
click_link 'No'
end

Resources