I'm writing a tests for my app with listed gems. I couldn't find how to set Capybara to work with backbone (ajax in all)
example test:
require 'spec_helper' describe "Main" do describe "GET /" do
it "displays articles" do
Article.create!(title:'title',body:'<p>body text</p>')
visit '/'
page.should have_content('body text')
end
end
end
and output of the test:
Failures:
1) Main GET / displays articles
Failure/Error: page.should have_content('body text')
expected there to be text "body text" in "Loading..."
# ./spec/features/main_spec.rb:8:in `block (3 levels) in <top (required)>'
"Loading..." is the pre ajax text in my view template...
The point is that I don't want to use Jasmine at the moment for this app
It looks like you are running Capybara with the default Rack::Test driver, which means no JavaScript. Rack::Test loads your app in process and fakes a browser DOM behind the Capybara API.
You need to use a driver that runs your tests in a real Web browser. There are a few different options: a Selenium driver comes with Capybara and runs your tests in a real browser (normally Firefox), others are implemented in separate gems, such as Poltergeist which uses PhantomJS and the headless WebKit browser.
There are instructions on the Capybara readme about setting up the right driver. You can switch a group of tests to use a JavaScript supporting driver by adding the js option to a describe block, e.g.:
describe "Main with JavaScript", :js => true do
# ...
end
Related
I an trying to organize code by making partial html.erb files that are shared frequently(e.g. _form.html.erb)
I want to check whether my partial code works well with different models/controllers, so I am manually doing CRUD from the views.
It would be nicer to test my code automatically using Rspec but I have no idea. Can anyone give me some guidance how to test controller code with Rspec?
To test controller and views together you write feature specs and request specs .
Request specs are lower level specs where you send HTTP requests to your application and write expectations (aka assertions in TDD lingo) about the response. They are a wrapper around ActionDispatch::IntegrationTest. Request specs should be considered the replacement for controller specs, the use of which are discouraged by by the RSpec and Rails teams.
# spec/requests/products_spec.rb
require 'rails_helper'
RSpec.describe "Products", type: :request do
describe "GET /products" do
let!(:products) { FactoryBot.create_list(:product, 4) }
it "contains the product names" do
get "/products"
expect(response).to include products.first.name
expect(response).to include products.last.name
end
end
end
Feature specs are higher level specs that focus on the user story. They often serve as acceptance tests. They use a browser simulator named Capybara which emulates a user clicking his way through the application. Capybara can also run headless browsers (headless chrome, firefox, phantom js, webkit etc) and "real" browsers through selenium. The minitest equivalent is ActionDispatch::SystemTestCase but RSpec features do not wrap it (it took minitest/testunit years to catch up here).
# Gemfile
gem 'capybara'
# spec/features/products_spec.rb
require 'rails_helper'
RSpec.feature "Products" do
let!(:products) { FactoryBot.create_list(:product, 4) }
scenario "when a user views a product" do
visit '/'
click_link 'Products'
click_link products.first.name
expect(page).to have_content products.first.name
expect(page).to have_content products.first.description
end
end
This specs tests the products#index and products#show action as well as the root page and the associated views.
Both types of specs have their strengths and weaknesses. Feature tests are good for testing large swaths of the application but are heavy. Request specs are faster and its easier to replicate a specific request that causes a bug/issue but you're basically just matching HTML with regular expressions which is highly limited.
To check whether partial code works well with different models/controllers. You can add render_views in controller specs.
How to test controller code with Rspec?
Read the official doc https://relishapp.com/rspec/rspec-rails/docs/controller-specs
And this page may help: https://thoughtbot.com/blog/how-we-test-rails-applications
I'm trying to make my tests pass, but cucumber is failing with a very confusing error, probably template related, that I'm not able to understand and fix.
Here is my Gemfile and Gemfile.lock:
https://gist.github.com/ngw/dada0c0658a9ef8b5573
You can assume that everything is on its latest version as of today, 28 March 2015, including rails, cucumber, ruby (2.2.0p0), database_cleaner, and so on.
The view that fails to render is a devise view that renders just fine on the browser.
Here is the exception raised:
Background: # features/users/sign_up.feature:6
Given I am not logged in # features/step_definitions/user_steps.rb:9
Scenario: User signs up with valid data # features/users/sign_up.feature:9
When I sign up with valid user data # features/step_definitions/user_steps.rb:13
undefined method `[]' for nil:NilClass
(in /Users/ngw/petswantpats/app/assets/stylesheets/application.css) (ActionView::Template::Error)
./app/views/layouts/application.html.haml:6:in `_app_views_layouts_application_html_haml___302582815389802583_70306431437360'
./features/step_definitions/user_steps.rb:6:in `sign_up'
./features/step_definitions/user_steps.rb:15:in `/^I sign up with valid user data$/'
./features/support/database_cleaner.rb:11:in `block in <top (required)>'
features/users/sign_up.feature:10:in `When I sign up with valid user data'
Then I should see a successful sign up message # features/step_definitions/user_steps.rb:18
Here are the incriminated views:
https://gist.github.com/ngw/95c0a0e6db86cfa0357f
Here is the content of application.css.scss:
https://gist.github.com/ngw/ab766e0cfb5167d2d76a
The failing step:
def sign_up
visit '/users/sign_up'
end
Is it something JS related? I'm using poltergeist with capybara, my env.rb has:
require 'capybara/poltergeist'
Capybara.javascript_driver = :poltergeist
If I use launchy to open it in the browser I have a white page (???) and no other usable information in my test.log...
Can someone help me on how to debug this? TIA
Soo, if Capybara can interface with the DOM and my app makes a form submit via AJAX and returns some JSON, can Capybara see that at all? I'm not finding any way to get to the AJAX response in the Capybara API.
Here's an example of kinda what I'm doing:
# Cucumber step_definition
Then(/^I should be able to create a household$/) do
click_link 'Next'
page.should have_selector 'form#household-form'
fill_in 'Name', with: name = Faker::Name.last_name
click_button 'Create'
page.wait_until do
page.evaluate_script('$.active') == 0 # really awesome hack to wait for ajax
end
#user.reload.households.first.name.should eq name
end
I'd rather not hit the database again to test the result, but instead do something like:
xhr.response_data.should be_json
Verifying that my json response is what I thought it should be.
I'm just experimenting here, trying to get used to Cucumber and Capybara.
You should mark your scenario / feature to run as a JavaScript feature by tagging it with #javascript:
#javascript
Scenario: Title goes here
What this will do is to tell Cucumber to run the selenium-webdriver gem which will launch a real browser (Firefox) and run the test inside that browser. The browser will of course evaluate the JavaScript and then Capybara will be able to see what it outputs.
When I use the visit method in Cucumber's step definitions and then run the step through Capybara's Selenium driver it's passed despite the controller isn't implemented.
Here's an example:
Feature
# features/one.feature
Feature: One
#selenium
Scenario: One
Given I visit the example page
Step definition
# features/step_definitions/example_steps.rb
Given /^I visit the example page$/ do
visit example_path
end
Route
# config/routes.rb
Example::Application.routes.draw do
resource :example
end
Controller
isn't implemented
Result
Feature: One
#selenium
Scenario: One
Given I visit the example page
1 scenario (1 passed)
1 step (1 passed)
0m18.162s
However, when I use the RackTest driver all works as it expected to be and the routing exception is risen unless a controller is implemented.
Here's the same example but with the usage of RackTest:
Feature
# features/one.feature
Feature: One
#rack_test
Scenario: One
Given I visit the example page
Result
Feature: One
#rack_test
Scenario: One
Given I visit the example page
uninitialized constant ExamplesController (ActionController::RoutingError)
./features/step_definitions/example_steps.rb:2:in `/^I visit the example page$/'
features/one.feature:5:in `Given I visit the example page'
Failing Scenarios:
cucumber features/one.feature:4 # Scenario: One
1 scenario (1 failed)
1 step (1 failed)
How can I force Capybara to raise the routing error when using the Selenium driver?
Thanks.
Ruby 1.9.2;
Ruby on Rails 3.1.0.rc1;
Cucumber 0.10.3;
Cucumber-rails 0.5.0;
Capybara 1.0.0.beta1;
Selenium-webdriver 0.2.0.
The Selenium driver does not fail when it receives a "failure" http code like 500. If you left your config/environments/test.rb at it's defaults, there should be a line config.action_dispatch.show_exceptions = false. So you can either set this to true or you would have to add some more steps to ensure the page is actually showing what you expect.
I've been using Capybara for integration/request testing, but have only just realised I can't do view testing with it.
This SO answer suggests Webrat and Capybara can be used in tandem; but the RSpec docs suggest one must choose between the two. Here's another github thread that suggests webrat can be used for views and capybara for integration.
I've found that if I include Webrat in my gemfile, I can use webrat for views with no problem, but my capybara-styled integration tests no longer work. Specifically, I get an error with the following simple example:
it "should have a Home page at '/'" do
visit '/'
page.should have_selector('title', :content => "Home page")
end
I get the error:
No response yet. Request a page first.
What's the best way (if any?) to get webrat and capybara to like eachother?
There's generally no reason to use both Webrat and Capybara. Pick one (probably Capybara). View tests are a bad idea and shouldn't be necessary in general; usually your integration tests should cover that ground.
In other words, fix your testing strategy and the problem will go away.
In general, I agree with Marnen about "just pick one of them, probably Capybara", but one possible reason to use both of them is gradual migration.
Say, you have a large test suite and you're migrating it to Capybara, but you'd like to let some of your old tests to stay "Webrat-driven" for some time.
Although, I didn't find ideal solution for this case, here's what I did:
# features/support/env.rb
...
if ENV['WITH_WEBRAT'].nil?
require 'capybara/rails'
require 'capybara/cucumber'
...
else
require 'webrat'
...
end
...
# config/cucumber.yml
...
default: --profile capybara
capybara: <% std_opts %> --tags ~#webrat features
webrat: <% std_opts %> --tags #webrat features WITH_WEBRAT=1
...
# features/webrat.feature
#webrat
...
# features/capybara.feature
...
Now, you can do cucumber to run your capybara-only test suite or cucumber -p webrat for your legacy Webrat features.
Not ideal, but it worked for me.