Cucumber `press button` failure (Capybara::ElementNotFound) - ruby-on-rails

I'm a relative newbie starting up a new Ruby on Rails app. I started by following a combination of instructions at https://github.com/intridea/omniauth, http://www.communityguides.eu/articles/16, http://intridea.com/2011/1/31/easy-rails-admin-login-with-google-apps-and-omniauth?blog=company . At the point everything appeared to work correctly, I started to write my very first cucumber features and steps. I was able to get a couple of steps up and running, but I've been bogged down on a step that I thought was built in. I have a form with two submit_tags but I can't get a scenario to successfully pass a basic And I press "button" step.
possibly relevant gems:
rails (3.1.0.rc4)
capybara (1.0.0)
cucumber (1.0.1)
cucumber-rails (1.0.2)
nokogiri (1.4.7)
gherkin (2.4.5)
rack-test (0.6.0)
selenium-webdriver (0.2.2)
section of the form in question:
<%= form_tag :controller => "services", :action => "newaccount" do %>
<%= submit_tag "confirm", :id => "confirm", :title => "confirm", :value => "confirm", :text => "confirm", :name => "confirm" %>
<%= submit_tag "cancel", :id => "cancel", :title => "cancel", :value => "cancel", :text => "cancel", :name => "cancel" %>
<% end %>
scenario in question:
Scenario: I register with a valid and currently active google account
Given I am not registered
When I sign in with a valid and currently active google account
And I press "confirm" # <-- THE PROBLEMATIC STEP
Then I should see "Your account has been created and you have been signed in!"
I think this is the relevant web_step (straight from the default web_steps.rb which I have not edited at all):
When /^(?:|I )press "([^"]*)"$/ do |button|
click_button(button)
end
relevant cucumber output:
Scenario: I register with a valid and currently active google account # features/auth_and_auth/initial_tests.feature:6
Given I am not registered # features/step_definitions/authentication_steps.rb:1
When I sign in with a valid and currently active google account # features/step_definitions/authentication_steps.rb:5
And I press "confirm" # features/step_definitions/web_steps.rb:52
no button with value or id or text 'confirm' found (Capybara::ElementNotFound)
(eval):2:in `click_button'
./features/step_definitions/web_steps.rb:53:in `/^(?:|I )press "([^"]*)"$/'
features/auth_and_auth/initial_tests.feature:9:in `And I press "confirm"'
Then I should see "Your account has been created and you have been signed in!" # features/step_definitions/web_steps.rb:105
relevant html output:
<input id="confirm" name="confirm" text="confirm" title="confirm" type="submit" value="confirm">
<input id="cancel" name="cancel" text="cancel" title="cancel" type="submit" value="cancel">
As is obvious, I've accounted for value, id, text, as well as name and title. I also saw a post that said the input type had to be specified as submit which it appears to have been. And I've tried it with both the confirm button and the cancel button.
After searching everywhere that I know about, and trying every suggestion that looked even remotely relevant, I'm at an impasse. What am I missing?

I'm not sure if the code below is the best way to deal with the problem I encountered, but it is getting the relevant step to pass.
When /^(?:|I )press "([^"]*)"$/ do |button|
# click_button(button) # the original web_steps.rb version that fails
%{I press (button)} # my revised version that passes
end
I'd still appreciate any feedback on:
why the original web_steps.rb version fails,
whether this is an appropriate approach or not, and
if there is a more 'rails' way to deal with this.

Related

Strange error while translating the word "admin" in Rails

Observe the following console output:
$ grep -IirF admin config/locales/
config/locales/static.el.yml: Administered: Χορηγήθηκε
config/locales/el.yml: admin: διαχειριστής
config/locales/system.el.yml: administered: Χορηγήθηκε
$ rails c
Running via Spring preloader in process 8176
Loading development environment (Rails 6.0.2.1)
irb(main):001:0> helper.t('admin1', locale: :el)
=> "admin1"
irb(main):002:0> helper.t('admin', locale: :el)
=> "διαχειριστής"
irb(main):003:0> helper.t('admin1', locale: :en)
=> "admin1"
irb(main):004:0> helper.t('admin', locale: :en)
=> {:js=>{true=>true, false=>false, :is_present=>"Is present", :is_blank=>"Is blank", :date=>"Date ...", :between_and_=>"Between ... and ...", :today=>"Today", :yesterday=>"Yesterday", :this_week=>"This week", :last_week=>"Last week", :number=>"Number ...", :contains=>"Contains", :is_exactly=>"Is exactly", :starts_with=>"Starts with", :ends_with=>"Ends with", :too_many_objects=>"Too many objects, use search box above", :no_objects=>"No objects found"}, :loading=>"Loading...", :toggle_navigation=>"Toggle navigation", :home=>{:name=>"Home"}, :pagination=>{:previous=>"« Prev", :next=>"Next »", :truncate=>"…"}, :misc=>{:search=>"Search", :filter=>"Filter", :refresh=>"Refresh", :show_all=>"Show all", :add_filter=>"Add filter", :bulk_menu_title=>"Selected items", :remove=>"Remove", :add_new=>"Add new", :chosen=>"Chosen %{name}", :chose_all=>"Choose all", :clear_all=>"Clear all", :up=>"Up", :down=>"Down", :navigation=>"Navigation", :root_navigation=>"Actions", :navigation_static_label=>"Links", :log_out=>"Log out", :time_ago=>"%{time} ago", :ago=>"ago", :more=>"Plus %{count} more %{models_name}"}, :flash=>{:successful=>"%{name} successfully %{action}", :error=>"%{name} failed to be %{action}", :noaction=>"No actions were taken", :model_not_found=>"Model '%{model}' could not be found", :object_not_found=>"%{model} with id '%{id}' could not be found"}, :table_headers=>{:model_name=>"Model name", :last_created=>"Last created", :records=>"Records", :username=>"User", :changes=>"Changes", :created_at=>"Date/Time", :item=>"Item", :message=>"Message"}, :actions=>{:dashboard=>{:title=>"Site Administration", :menu=>"Dashboard", :breadcrumb=>"Dashboard"}, :index=>{:title=>"List of %{model_label_plural}", :menu=>"List", :breadcrumb=>"%{model_label_plural}"}, :show=>{:title=>"Details for %{model_label} '%{object_label}'", :menu=>"Show", :breadcrumb=>"%{object_label}"}, :show_in_app=>{:menu=>"Show in app"}, :new=>{:title=>"New %{model_label}", :menu=>"Add new", :breadcrumb=>"New", :link=>"Add a new %{model_label}", :done=>"created"}, :edit=>{:title=>"Edit %{model_label} '%{object_label}'", :menu=>"Edit", :breadcrumb=>"Edit", :link=>"Edit this %{model_label}", :done=>"updated"}, :delete=>{:title=>"Delete %{model_label} '%{object_label}'", :menu=>"Delete", :breadcrumb=>"Delete", :link=>"Delete '%{object_label}'", :done=>"deleted"}, :bulk_delete=>{:title=>"Delete %{model_label_plural}", :menu=>"Multiple delete", :breadcrumb=>"Multiple delete", :bulk_link=>"Delete selected %{model_label_plural}"}, :export=>{:title=>"Export %{model_label_plural}", :menu=>"Export", :breadcrumb=>"Export", :link=>"Export found %{model_label_plural}", :bulk_link=>"Export selected %{model_label_plural}", :done=>"exported"}, :history_index=>{:title=>"History for %{model_label_plural}", :menu=>"History", :breadcrumb=>"History"}, :history_show=>{:title=>"History for %{model_label} '%{object_label}'", :menu=>"History", :breadcrumb=>"History"}}, :form=>{:cancel=>"Cancel", :basic_info=>"Basic info", :required=>"Required", :optional=>"Optional", :one_char=>"character", :char_length_up_to=>"length up to", :char_length_of=>"length of", :save=>"Save", :save_and_add_another=>"Save and add another", :save_and_edit=>"Save and edit", :all_of_the_following_related_items_will_be_deleted=>"? The following related items may be deleted or orphaned:", :are_you_sure_you_want_to_delete_the_object=>"Are you sure you want to delete this %{model_name}", :confirmation=>"Yes, I'm sure", :bulk_delete=>"The following objects will be deleted, which may delete or orphan some of their related dependencies:", :new_model=>"%{name} (new)"}, :export=>{:confirmation=>"Export to %{name}", :select=>"Select fields to export", :select_all_fields=>"Select All Fields", :fields_from=>"Fields from %{name}", :fields_from_associated=>"Fields from associated %{name}", :display=>"Display %{name}: %{type}", :options_for=>"Options for %{name}", :empty_value_for_associated_objects=>"<empty>", :click_to_reverse_selection=>"Click to reverse selection", :csv=>{:header_for_root_methods=>"%{name}", :header_for_association_methods=>"%{name} [%{association}]", :encoding_to=>"Encode to", :encoding_to_help=>"Choose output encoding. Leave empty to let current input encoding untouched: (%{name})", :skip_header=>"No header", :skip_header_help=>"Do not output a header (no fields description)", :default_col_sep=>",", :col_sep=>"Column separator", :col_sep_help=>"Leave blank for default ('%{value}')"}}, :history_rollback=>{:cancel=>"Cancel", :confirm=>"Are you sure?", :table_headers=>{:changes=>"Changes", :field=>"Field", :rollback=>"Rollback", :view_changes=>"View changes"}, :rollback_destroy=>"Rolled back newly-created record by destroying it.", :rollback_success=>"Rolled back changes to this record.", :rollback_impossible=>"Couldn't rollback. Sorry.", :version_not_found=>"Version does not exist.", :rollback_violates_foreign_key=>"Couldn't rollback: this model links to another model, which doesn't exists."}}
Translation seems to work correctly, except for a single word: 'admin'
Can someone explain this error, and how to overcome it?
This most likely has to do with a conflict with some other gem that adds an admin namespace, like maybe ActiveAdmin or rails_admin, or maybe a role authorization plugin. That's why it's returning a hash instead of a single string value.
Some other code or gem has loaded the admin key to look something like this:
en:
admin:
js:
'true': true
'false': false
is_present: Is present
....etc....
I would suggest nesting your key to avoid the conflict with something like:
en:
user_type:
admin: Administrator
helper.t('user_type.admin')
I would also suggest setting up the i18n-tasks gem, which can find and correct issues with translation files, as part of your CI or test suite, which I believe would have detected this conflict with the command i18n-tasks health and shown that admin is a dupilcate key, so when your yaml files and the gem's get combined, only the last one to write to the translations hash will be preserved.

Rails, Capybara - click_link on remote links doesnt work

I'm using Capybara to test my project. But i have a problem.
I have some remote forms on my project. They add records via ajax. When i'm testing with capybara it works well on development environment. It visits the page, fills in the form and submits. Booom, record has been added and test didnt fail.
But when i run rspec with test environments i'm getting unknown format exception.
1) add new address user adds new address
Failure/Error: find("input[value='Adres Ekle']").click
ActionController::UnknownFormat:
Account::AddressesController#create is missing a template for this request format and variant.
request.formats: ["text/html"]
request.variant: []
# ./spec/features/user_add_new_address_spec.rb:28:in `block (2 levels) in <top (required)>'
I've also tried to respond via js from controller like;
def create
request.format = :js
end
Then it returns;
1) add new address user adds new address
Failure/Error: find("input[value='Adres Ekle']").click
ActionController::UnknownFormat:
Account::AddressesController#create is missing a template for this request format and variant.
request.formats: ["text/javascript"]
request.variant: []
# ./spec/features/user_add_new_address_spec.rb:28:in `block (2 levels) in <top (required)>'
And my scenario if u want more info;
scenario 'user adds new address' do
expect(page).to have_content 'Kayıtlı Adreslerim'
find("a[title='Adres Ekle']").click
expect(page).to have_content 'Yeni Adres Ekle'
expect(page).to have_content 'Adres Başlığı'
fill_in 'address[name]', with:'Izmir Ofisi'
select('Izmir', :from => 'address[city_id]')
fill_in 'address[address]', with: 'Lorem ipsum dolor sit amet.'
find("input[value='Adres Ekle']").click # It submits remote: true form.
expect(page).to have_content 'Success!'
end
PS: my create action doesnt render something like that.
its like;
def create
#new_address = Address.new
#address = #current_account.addresses.new(address_params)
if #address.save
#check = true
else
#check = false
end
end
it renders: create.js.erb
<% if #check %>
if($('.addresses').length) {
$('.addresses').append('<%= j(render('account/addresses/address', address: #address)) %>');
}
if($('#did-addresses').length){
$('#did-addresses').append("<%= "<option selected='true' value='#{#address.id}'>#{#address.name}</option>".html_safe %>").selectpicker('refresh');
}
$('#new-address').html('<%= j(render('account/addresses/form', new_address: #new_address)) %>');
swal({
type: 'success',
title: "<%= t('response.success') %>",
text: "<%= t('flash.actions.create.notice', resource_name: Address.model_name.human) %>",
timer: 2000
});
quickview.close('#new-address');
<% else %>
<% #address.errors.each do |error| %>
<% end %>
<% end %>
$('.preloader').fadeOut();
I was facing the same case in rails 6 but I fixed it be adding js: true to the scenario and it automatically worked well.
scenario 'Should delete the feature', js: true do
# Your logic
# Your expectations
end
Since copying your development config over your test config fixed your issue, it sounds like you probably an error in one of your JS files. Normally in the test and production environment all of your JS assets get concatenated into one file which means an error in any one of them can prevent the code in the others from being executed. In the development environment each JS file is loaded separately which means an error in any file can only affect the rest of the code in that file. Check your the console in your browser for any JS errors when going to the page in question and fix them.

Capybara cannot find a link on a modal which changes on button press

I have a rails project using rspec 3.4.0 capybara 2.6.2 and capybara-webkit 1.8.0.
I am writing a feature test for a flow on my site which looks like the following:
scenario "Buyer creates a seller profile", :js => true do
click_link("SELL ON MYSITE",match: :first)
expect(page).to have_text("Reach thousands of customers in your area")
click_link("Create an Activity",match: :first)
expect(current_path).to eql (new_seller_profile_path)
fill_in "seller_profile[business_name]", :with => "Test company"
fill_in "seller_profile[business_email]", :with => "test#email.com"
fill_in "seller_profile[business_phone_number]", :with => "07771330510"
fill_in "seller_profile[business_description]", :with => "This is a test company"
find('label[for="social"]').click
find("#facebook-placeholder").click
fill_in "seller_profile[business_facebook_url]", :with => "https://www.facebook.com/test"
click_button("CREATE AN ACTIVITY")
------this button opens a modal after the page changes --------
fill_in "seller_profile[requested_postcode]", :with => "EH21 8PB"
click_button("Submit")
save_and_open_screenshot
------this is where it goes wrong-------
click_link("Continue")
expect(page).to have_text("Choose the type of activity that you want to create")
end
The click_link continue fails with error:
Failure/Error: click_link("Continue")
Capybara::ElementNotFound:
Unable to find link "Continue"
The link actually does exist - when you click on the submit button some javascript executes which changes the contents of the modal to display some new text and a new button. However for some reason click_link does not wait or look in the modal, it fails straight away.
Having added a save_and_open_screenshot call we can see this situation as the modal javascript has yet to execute as we can still see the submit button :
Interestingly the mouse seems to not be on the Submit button as it should have just clicked it?
How can I make the click_link wait until the continue button appears?!
This is the javascript which executes on press of 'submit' added to the modal which changes it:
$('#gate .modal-body .intro').text('Congratulations, we are available in your location, please continue to create your activity.');
$('#gate .modal-footer').append('<a class="btn btn-lg btn-primary" href="/events/new/">Continue</a>');
Seemingly adding a couple of sleeps in has fixed it. I don't know if this is 'right' solution. If somebody has a better way or potentially a better way I would love you to help me find it :
fill_in "seller_profile[requested_postcode]", :with => "EH21 8PB"
sleep 2
click_button("Submit")
sleep 2
click_link("Continue")

Capybara isn't checking a checkbox in rspec feature test

I am attempting to create a feature test where a checkbox needs to be checked and for whatever reason Capybara is not checking the box.
I am using:
rspec: 3.0.4 and capybara: 2.4.1
When I print out a snapshot of the view, the checkbox isn't checked.
When I run the checkbox code in pry it returns the string "checked" but when I print a snapshot the checkbox still is not checked and my test does not pass. I'm curious if there is another way to get this checkbox to check.
Here is my current code so far:
Feature Test:
background do
discussion_group
#user2 = FactoryGirl.create(:user)
add_user_to_user_role_for_group(group, #user2)
admin_login
add_user_to_admin_role_for_group(group, #user)
visit groups_path
click_on 'Email Group'
end
scenario 'sending a valid email' do
valid_form
expect(page).to have_content group_email_success_notification
expect_count_of_deliveries_to_be 1
end
Macro:
def valid_form
fill_in 'group_email_subject', with: new_text
fill_in 'group_email_body', with: Faker::Lorem.words(200).join("\s")
check "group_email_#{#user2.id}_"
click_on "Send Email"
end
The output of my test is that I must have 1 user selected meaning that I don't have a user checked. When I run the check line in console here is what I get:
[10] check('group_email_10_')
=> "checked"
Any help is greatly appreciated.
I'd use:
page.check('insert #id, .class, or value')\
for example:
input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes"
page.check('puppy_gooddog') or page.check('puppy[gooddog]')

Rails: Capybara doesn't find a div element

I'm using Capybara with RSpec to check my Rails project.
I'm testing errors when form fields are not correctly filled. Here is the form (using haml):
= form_tag '/objects', :class => 'objects-form' do
%ul
%li= select_tag 'object', options_for_select([['Select an object', ''], ['Car', 'CAR'], ['Keys', 'KEYS'], ['Ambrella', 'AMBRELLA']]), :id => 'select-object'
%li= text_field_tag :quantity, nil
%li= submit_tag 'Buy', :id => 'object-submit'
When an error occurs (in this case, not choosing an object but only a quantity), a flash message is displayed (with a .flash-error class name):
- flash.each do |type, msg|
= content_tag :div, msg, :class => "flash-#{type}", :id => 'flash-msg'
So, here is my Capybara test:
it 'Should return error when no object selected' do
within 'form.objects-form' do
fill_in 'quantity', :with => '1'
click_button 'object-submit'
current_path.should == objects_path
save_and_open_page
page.should have_css 'div.flash-error'
end
end
But I get the following Capybara error:
Failure/Error: page.should have_css 'div.flash-error'
expected #has_css?("div.flash-error") to return true, got false
The opened page (using save_and_open_page) shows the error message with the appropriate div:
div#flash-msg.flash-error
I'm using the latest version of Capybara (since many similar problems on Stackoverflow are relative to old versions of Capybara) using gem 'capybara', :git => 'https://github.com/jnicklas/capybara.git'
Any idea? Thank in advance.
EDIT:
Corrected typing mistake on Capybara code, as detected by Alex.
The problem is your selector you are using in capybara is div#flash-error but your div is div#flash-msg.flash-error or more simply div.flash-error.

Resources