I'm doing an integration test wherein I need to click an html class element and it will go to controller action using Ajax.
Here's my html slim code:
table.table-default
thead
tr Title
tbody
tr.title
td Hello World
The JavaScript handles the click event on the tr
$(function() {
$('.title').click(function() {
$.ajax({
type: 'GET',
url: "/admin/dashboards/load_info/
});
})
})
I raised an error in a controller action to test if it will go to the controller
class Admin::DashboardsController < Admin::BaseController
def load_info
raise 'hello'.inspect
end
end
When I test on browser it raises hello
This is my current setup for testing:
gem "minitest-rails"
group :test do
gem 'shoulda', '~> 3.5'
gem 'shoulda-matchers', '~> 2.0'
gem 'rails-controller-testing'
gem 'minitest-spec-rails'
gem 'm', '~> 1.5.0'
gem 'minitest-rails-capybara'
gem 'database_cleaner'
gem 'phantomjs', :require => 'phantomjs/poltergeist'
gem 'poltergeist'
end
My test suit is this:
class DashboardFlowTest < Capybara::Rails::TestCase
before(:all) do
Capybara.current_driver = :poltergeist
end
test "Given I'm at dashboard page when I click the table row it should redirect me to load_info' do
visit 'admin/dashboards'
find('.title').click
assert_current_path admin_dashboards_load_info_path
end
end
The error I'm getting is:
Capybara::Poltergeist::StatusFailError: Request to 'http://127.0.0.1:50102/admin/dashboards/' failed to reach server, check DNS and/or server status - Timed out with no open resource requests
When I run the test it doesn't raises an error. I'm suspecting that the click function on the test only supports link or button or my test is not JavaScript enabled.
Related
How can I check if the css class was added to the div after the button click?
I have a button with class "btn-success" and a modal form which by default doesn't have "show" class, but after clicking on the button the "show" class is added to the modal.
My test:
it 'shows up popup with form' do
modal_window = page.find('#data-modal')
expect(modal_window[:class]).not_to include('show')
page.find('.btn-success').click
expect(modal_window[:class]).to include('show')
end
My Gemfile:
group :development, :test do
gem 'rspec-rails', '~> 3.8'
gem 'factory_bot_rails'
gem 'rails-controller-testing'
gem 'webmock'
gem 'capybara'
gem 'selenium-webdriver'
gem 'rails-controller-testing'
end
To do exactly what you're asking the easiest solution would be something like
it 'shows up popup with form' do
expect(page).not_to have_css('#data-modal.show')
page.find('.btn-success').click
expect(page).to have_css('#data-modal.show')
end
However you really shouldn't be testing for the existence of specific classes in feature tests. Instead you should be testing that the modal actually appears. Since this is JS driven behavior it would mean making sure your test is running with a JS capable driver, making sure you haven't set Capybara.ignore_hidden_elements to false, and then doing
it 'shows up popup with form' do
# Should initially be hidden so won't be found
expect(page).not_to have_css('#data-modal')
page.find('.btn-success').click
# Should now be found
expect(page).to have_css('#data-modal')
end
The goal is for command...
bin/rails generate custom_scaffold Thing
... to generate the following 6 files:
db/migrate/201812031331_create_things.rb
app/models/thing.rb
app/controllers/things_controller.rb
app/serializers/thing_serializer.rb
test/fixtures/things.yml
test/integration/requests/things_request_test.rb
... using Rails 5.
My current setup does generate app/models/thing.rb but does not populate it with Thing.
Expected:
class Thing < ApplicationRecord
end
Currently:
class <%= class_name %> < ApplicationRecord
end
I have read through these Rails guides but to little avail.
Does anyone have a working example?
My setup:
# lib/generators/custom_scaffold/custom_scaffold_generator.rb
class CustomScaffoldGenerator < Rails::Generators::NamedBase
source_root File.expand_path('templates', __dir__)
def create_files
copy_file 'migration.rb', "db/migrate/#{timestamp}_create_#{plural_name}.rb"
copy_file 'model.rb', "app/models/#{file_name}.rb"
copy_file 'controller.rb', "app/controllers/#{plural_name}_controller.rb"
copy_file 'serializer.rb', "app/serializers/#{file_name}_serializer.rb"
copy_file 'fixture.yml', "test/fixtures/#{plural_name}.yml"
copy_file 'request_test.rb', "test/integration/requests/#{plural_name}_request_test.rb"
end
private
def timestamp
Time.now.utc.strftime('%Y%m%d%H%M%S')
end
end
# lib/generators/custom_scaffold/templates/model.rb
class <%= class_name %> < ApplicationRecord
end
# lib/generators/custom_scaffold/templates/controller.rb
module V1
module Public
class <%= class_name.pluralize %>Controller < ApplicationController
end
end
end
# lib/generators/custom_scaffold/templates/migration.rb
# Ignore for now
# lib/generators/custom_scaffold/templates/serializer.rb
# Ignore for now
# lib/generators/custom_scaffold/templates/fixture.yml
# Ignore for now
# lib/generators/custom_scaffold/templates/request_test.rb
# Ignore for now
# Gemfile
source 'https://rubygems.org'
ruby '2.4.1'
gem 'rails', '~> 5.1.6'
gem 'puma', '~> 3.7'
gem 'pg'
gem 'rack-cors', require: 'rack/cors'
gem 'olive_branch'
gem 'fast_jsonapi'
gem 'awesome_print'
gem 'byebug', '~> 10.0', groups: %i[development test]
gem 'yaml_db'
group :development do
gem 'listen', '>= 3.0.5', '< 3.2'
gem 'mina', '~> 1.2', require: false
gem 'mina-puma', require: false
gem 'rubocop', require: false
gem 'annotate', require: false
end
You need to specify the file as a Thor template. Rails uses Thor templates for generating templates with ERB style code inside them.
Replace:
copy_file 'model.rb', "app/models/#{file_name}.rb"
With:
template 'model.rb.tt', "app/models/#{file_name}.rb"
By adding the .tt extension you're telling the generator to handle the file as a Thor template, which will interpret the Ruby code (ERB style) inside the file and then create a file with that same name minus the .tt extension. Any file you have without the .tt extension the generator will copy wholesale, without executing any of the code inside.
A useful tip: Sometimes you want to leave some ERB code inside a Thor template file without it being executed. By default any ERB style tags inside a .tt file will be process and in it's place a string will be written to the output file. You can avoid the processing of ERB tags but using a double percent sign in the tag.
For example, lets say you have a file named foo.erb.tt, which will create the file foo.erb when your generator runs. Let's also say we have a article_name variable and it's value is Breaking News
If you put <%= article_name %> in the file it will write Breaking News to the foo.erb.
If you put <%%= article_name %> (notice the %%) it will write <%= article_name %>to the foo.erb.
I found the following reference handy when learning this stuff.
Rails Application Templates article at Rails Guides.
Creating and Customizing Rails Generators & Templates article at Rails Guides.
Thor Actions Docs these are the commands used in our template.rb file.
Thor comes with several actions that help with script and generator tasks. You might be familiar with them since some came from Rails Templates. They are: say, ask, yes?, no?, add_file, remove_file, copy_file, template, directory, inside, run, inject_into_file and a couple more.
I'm trying to test a Rails application that connects to a remote Oracle database using the Sequel gem. Since the user needs to be logged in in order to use the site, I'm using WebMock. However, because WebMock stops all requests to outside sources, I get the error Sequel::DatabaseConnectionError: OCIError: ORA-12541: TNS:no listener every time I run my tests. How would I mock the database connection? Should I try something else instead?
I'm not sure what code to provide, so here are some snippets that may relate to possible solutions:
database_connection.rb:
class DatabaseConnection
##db = nil
def self.get_db
##db ||= Sequel.connect(Settings.db.main.to_hash)
end
def self.db_query(query)
get_db[query]
end
end
In spec_helper.rb:
require 'webmock/rspec'
WebMock.disable_net_connect!(allow_localhost: true)
RSpec.configure do |config|
config.before(:each) do
stub_request(:post, "/path/to/third/party").
with(:body => "request body").
to_return(:status => 200, :body => "", :headers => {})
end
# ... rest of the code
end
Relevant gems from Gemfile:
gem 'rails', '4.0.2'
gem 'ruby-oci8', git: 'https://github.com/kubo/ruby-oci8.git'
group :development, :test do
gem 'rspec-rails', '~> 3.2.0'
end
group :test do
gem 'webmock' # 1.21.0
gem 'capybara' # 2.4.4
end
Sequel ships with a mock adapter for exactly this purpose:
##db ||= Sequel.connect('mock://oracle')
See the documentation for details about how to use the mocked database:
http://sequel.jeremyevans.net/rdoc-adapters/classes/Sequel/Mock/Database.html
http://sequel.jeremyevans.net/rdoc-adapters/classes/Sequel/Mock/Dataset.html
I have a test that keeps failing because the button is initially disabled until I check a checkbox which then removes the disabled attribute from the button.
%button.btn.btn-success{id: 'registration_button', :type => "submit", :disabled=>'disabled'} Register
$('#tos_acceptance').click ->
tosChecked = $('#tos_acceptance').is(':checked');
if tosChecked
$('#registration_button').attr('disabled', false);
else
$('#registration_button').attr('disabled', 'disabled');
The problem I keep getting is that capybara cannot find the button.
Unable to find button "Register" (Capybara::ElementNotFound)
This is part of my test:
When(/^User goes to the registration page and enters (.*) and (.*) and (.*)$/) do |email, password, password_confirmation|
within all('.nav')[1] do
click_link('Register')
end
current_path.should == new_user_registration_path
page.should have_content('Please create your new account')
fill_in('user[email]', :with => email)
fill_in('user[password]', :with => password)
fill_in('user[password_confirmation]', :with => password_confirmation)
check 'tos_acceptance'
click_button('Register')
end
Here is my related Gemfile:
group :test do
gem 'rspec-rails'
gem 'cucumber-rails', :require => false
gem 'capybara'
gem 'database_cleaner'
gem 'email_spec'
gem 'spork'
gem 'launchy'
gem 'autotest'
gem 'turn', :require => false
gem 'minitest', '=4.7.5'
gem 'minitest-reporters', '>= 0.14.23'
How do I enable the button (with the javascript logic) so that this test passes? If I remove the disabled attribute, my tests pass fine, so I'm pretty confident that the issue is with enabling JS for the cucumber tests.
I'm not sure, but it seems, you didn't enable javascript for your Cucumber scenario.
You should add #javascript before your scenario to enable javascript for this scenario (selenium web driver will be used by default): https://github.com/jnicklas/capybara#using-capybara-with-cucumber
If you don't want to use selenium and want to enable headless javascript driver (like capybara-webkit or poltergeist), you'll need to add a gem to your Gemfile and change javascript driver as described here: https://github.com/jnicklas/capybara#drivers
I'm assuming it's not actually disabled-- so I don't think the issue is Capybara-- at least that's my guess-- You have to actually remove the disabled attribute. This doesn't address the test-- but in my experience the disabled attribute must actually be removed from the DOM to make the button disabled.
$('#tos_acceptance').click ->
tosChecked = $('#tos_acceptance').is(':checked');
if tosChecked
$('#registration_button').removeAttr('disabled');
else
$('#registration_button').attr('disabled', 'disabled');
My Gemfile looks like this:-
group :test do
# Pretty printed test output
gem 'capybara'#,'1.1.2'
gem 'cucumber-rails','1.2.1'
gem 'cucumber','1.1.4'
gem 'rspec-rails','2.8.1'
gem 'rspec-cells','0.1.2'
gem "factory_girl_rails"
gem "guard-rspec"
gem "minitest"
gem 'headless'
gem 'minitest-rails'
gem 'minitest-rails-capybara'
end
minitest_helper.rb looks like :-
ENV["RAILS_ENV"] = "test"
require File.expand_path("../../config/environment", __FILE__)
require "minitest/autorun"
require "capybara/rails"
class ControllerTest < MiniTest::Spec
include Rails.application.routes.url_helpers
include Capybara::DSL
register_spec_type(/integration$/, self)
end
And my products_controller_test.rb looks like this:-
require "minitest_helper"
describe "Products Controller" do
it "shows product's name" do
uname="Glasses"
product1 = Product.create!(:name => uname, :description => uname, :no_of_items => 3,:fee_percentage => 4)
visit products_path
page.text.must_include "Glasses"
end
end
BUT..after executing ruby -Itest test/controllers/products_controller_test.rb
I get no error,no indication to show that this test class has been loaded :-
ruby -Itest test/controllers/products_controller_test.rb
:public is no longer used to avoid overloading Module#public, use :public_folder instead
from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/resque-1.19.0/lib/resque/server.rb:12:in `<class:Server>'
Loaded suite test/controllers/products_controller_test
Started
Finished in 0.004953 seconds.
0 tests, 0 assertions, 0 failures, 0 errors, 0 skips
its first time i am using Minitest...
Your Gemfile is a little heavy... If you remove all the RSpec references, you'll run just fine.
(The "describe" and "it" methods are being usurped by rspec)
Remove:
gem 'rspec-rails','2.8.1'
gem 'rspec-cells','0.1.2'