How to test ActiveAdmin? - ruby-on-rails

I'm using ActiveAdmin on my rails project, and I would like to know how test it, like how does activeadmin usually test? Since there's no tutorial on the internet, is it necessary to test it?, like this answer I found https://softwareengineering.stackexchange.com/questions/256557/should-i-be-writing-feature-or-request-specs.

ActiveAdmin is built on Rails so use Rails testing. In particular I can recommend Thoughtbot's approach. Here is a typical feature spec using RSpec and Capybara:
feature City do
scenario 'new city' do
click_link 'Cities'
click_link 'New City'
fill_in 'Name', with: 'Wellington'
click_button 'Create City'
expect(page).to have_selector 'div.flash', text: 'City was successfully created.'
end
end

Related

How to test Cocoon gem's nested forms with Capybara and Minitest in Rails

Is it possible to use Minitest and Capybara to test multi-step forms in Rails? All of the examples I've read online and in Stackoverflow are using Rspec. For instance, this question.
It seems like this should be something that is possible to do in Minitest though. I'm trying to test a nested form that uses the Cocoon gem and looks like this:
Before clicking the "New Option" button:
After clicking the "New Option" button:
But, my test keeps failing at this step:
click_link 'New Option'
If I add 'save_and_open_page' after click_link 'New Option' the browser shows that field that should be revealed by click_link 'New Option'. It works when I test it manually on my development server though. This New Option button is generated by Cocoon with this:
<%= link_to_add_association 'New Option', f, :options %>
So that leads me to believe that it's not finding the field on the next step because javacript is not working in Capybara and Minitest. But I'm not sure.
I have Capybara.javascript_driver = :webkit in my test_helper.rb file, so the javascript driver should be working
Is this a problem with Minitest? Or am I doing something wrong in my test? If I view source on the page that is generated by save_and_open_page I can see the hidden fields in the New Option link tag. Here's what that looks like:
Based on this question, it seems like I need to do something like this:
click_link "New Option"
first("input[name='product[options_attributes][new_options][name]']").set("New Option Name")
But that gives me the error:
Capybara::ExpectationNotMet: expected to find css "input[name='product[options_attributes][new_options][name]']" at least 1 time but there were no matches
It seems like there's something wrong with Minitest & Capybara testing Javascript because it seems to fail at the "New Option" link and not after that. I can't tell if it's a problem with Javascript related to Minitest and Capybara or if I'm not accessing the field properly in Minitest.
Thanks to Thomas Walpole for pointing out that capybara-webkit was the problem. Along with some help from this article, here's what I needed to change the test passing:
Added these to my Gemfile:
group :test do
gem 'selenium-webdriver'
gem 'webdrivers'
end
Added this to my test_helper.rb:
class ActionDispatch::IntegrationTest
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app, browser: :chrome)
end
Capybara.javascript_driver = :chrome
Capybara.configure do |config|
config.default_max_wait_time = 10 # seconds
config.default_driver = :selenium
end
end
And then my test:
test 'Account owners can add a new product as well as options and choices' do
visit new_product_path(as: #account_owner)
assert_title 'Add New Product'
assert_selector 'h1', text: 'Add New Product'
fill_in 'product_name', :with => #new_product.name
# Users can add product options through the nested form
click_link 'New Option'
within('.product_options_name') do
first('input.form-control').set("#{#t_shirt_colors.name}")
end
click_link 'Add Choice'
within('.product-option-choice') do
first('input.form-control').set("#{#red_color_choice.name}")
end
click_button 'Create Product'
assert_selector '.alert', text: 'Product was successfully created.'
end

How to write Rails rspec feature test for a custom gem?

Where may I find guides on how to write a Rails rspec test that utilizes the ajaxful_rating gem. The test I'm writing is something like the one below.
https://github.com/edgarjs/ajaxful-rating
require "rails_helper"
RSpec.feature "Users can create new review" do
scenario "with valid attributes" do
# Put in a 5 star rating here.
fill_in "Review", with: "This place is pretty good."
click_button "Create Review"
expect(page).to have_content "Review has been created."
end
end
This could be a very broad answer however if you want to learn how you can write test case in rspec, this documentation can be helpful to understand the concept of what is test case and how you can make.

Dynamic expectations in Rspec

I am trying to test a dynamic url path through an Rspec expectation, as below:
describe 'registering a user' do
context 'with valid data' do
it 'confirms user registration' do
visit '/users/new'
fill_in 'Name here...', with: 'johnny bloggs'
fill_in 'Your email here...', with: 'test1#test.com'
click_button 'Notify me'
expect(current_path).to eq '/users/#user.id'
expect(page).to have_content "johhny"
expect(page).not_to have_content "Sign up"
end
end
end
This is a feature test not a model unit test so I suppose this sort of object attribute , #user.id, expectation shouldn't be in a feature test. But testing the redirection to a certain path i guess is a valid thing for a feature test to be checking, and a key part of the functionality that i'm testing is that the action redirects to an object specific show page?!
So a) how should i correctly be testing this redirect thats new path involves a dynamic attribute and b) whether or not the correct thing to be doing here is testing a 'dynamic attribute' how would it be possible to test dynamic content within an rspec test? .erb perhaps?
Thank you in advance for the enlightenment.
You can use plain string interpolation:
expect(current_path).to eq "/users/#{ User.last.id }"
Or a route helper:
expect(current_path).to eq user_path(User.last)

Nesting scenarios with feature specs in Rspec Rails 3

I'm using Rspec Rails with Capybara for testing and I want to use the new feature spec in RSpec Rails 3 as they read more as customer tests and acceptance tests. However, one thing I find missing from the older (Describe/It) style is nesting. When trying to nest scenarios or use background inside any scenario block, I get an undefined method error. Is there anyway I could achieve nesting with feature specs to get something like this (from Michael Hartl's Ruby On Rails Tutorial:
describe "Authentication" do
subject { page }
describe "authorization" do
let(:user) { FactoryGirl.create(:user) }
describe "for non-signed in users" do
describe "when attempting to visit a protected page" do
before { visit edit_user_path(user) }
it "should redirect_to to the signin page" do
expect(page).to have_title('Sign in')
end
describe "after signing in" do
before do
valid_signin user, no_visit: true
end
it "should render the desired protected page" do
expect(page).to have_title('Edit user')
end
Or should I be thinking in a different way about integration tests ?
As described in https://www.relishapp.com/rspec/rspec-rails/docs/feature-specs/feature-spec, feature corresponds to describe and scenario corresponds to it. So, you can nest instances of feature, but you cannot nest a scenario within a scenario, just as you cannot nest an it within a it.
Nested feature with scenarios is available in Capybara version 2.2.1
In Gemfile include
gem "capybara", "~> 2.2.1"
and bundle install
As per official documentation of Capybara
feature is in fact just an alias for describe ..., :type => :feature,
background is an alias for before, scenario for it, and given/*given!*
aliases for let/*let!*, respectively.
Here is the original issue and later it was accepted and merged in version 2.2.1

why capybara can't submit directly to put action?

I was watching Michael Hartl's Rails tutorial, In chapter 9.2.2, Hartl says that we can't use capybara to issue put/patch requests directly to a model,
This was the test code:
describe "for wrong users" do
let(:user) { FactoryGirl.create(:user) }
let(:wrong_user) { FactoryGirl.create(:user, email: "wrong#example.com") }
before { valid_signin user}
describe "when submitting a PATCH request to users#update" do
before { patch user_path(wrong_user) }
specify { expect(response).to redirect_to root_path}
end
end
and valid_signin is like this, intially:
def valid_signin(user, options = {})
visit signin_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
These tests don't work, as when we issue a put request, we can't use capybara to do this.
So is it like this, that we can't use capybara to test any put/patch requests? And what we should do in general when we need to test put/patch requests and we can't use capybara?
Capybara is for Behaviour Driver Development. Who's behaviour? Human beings.
Can a human being patch? Can he put? He can't. Only computers can.
Can a human being visit, fill_in, click_button? Yes he can. This is what Capybara for.
Bottom line, put computers' actions into unit testing and controller testing, mimic human beings in integration testing by Capybara.

Resources