I'm using cucumber to test my rails 3.1 application and i'm using devise for authentication.
I need to test if current user email is the same with the one used during authorization.
The problem is that devise helpers are not available in cucumber step definition.
Is there any solution to make devise helpers available in cucumber step definitions?
i tried this:
Cucumber::Rails::World.send('define_method', 'current_user') do
#current_user ||= (session[:user] && User.find(session[:user])) || :false
end
but that didn't help.
Add this to the step definitions file that needs to use it:
World(Devise::TestHelpers)
While this makes the 'sign_in' and 'sign_out' methods available, they can't actually be used from Cucumber, so this DOES NOT WORK. The comments at the top of devise's file says "Do not use Devise::TestHelpers in integration tests". See: https://github.com/plataformatec/devise/blob/master/lib/devise/test_helpers.rb
Unfortunately, cucumber steps don't have access to the web request object and session parameters. It appears the only way to do this is to repeatedly perform the login web requests at the start of each scenario. Boring. I find it odd that cucumber can directly manipulate the test rails app's database but not the web request/session. In any case, this old post shows a good example of refactoring steps to be in a module that can be shared by many steps easily: http://drnicwilliams.com/2009/04/15/cucumber-building-a-better-world-object/
If anyone else has an answer for how a scenario can set the logged in state without having to do all the capybara web calls, I'd love to hear it.
You can do this to stub log ins in Cucumber:
https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara
put the lines in support/env.rb:
include Warden::Test::Helpers
After do
Warden.test_reset!
end
then you can do:
user = create :user
login_as :user, scope: :user
BUT, the login_as helper does not redirect you to the next page after logging you in. It just logs you in.
So you must explicitly go to the next page you are testing as a logged in user.
So you must do another step to explicitly do that, e.g. visit '/'
Something that may help is https://github.com/ngty/cross-stub - this allows you to stub methods cross process, which is necessary for cucumber testing sometimes
Related
I am writing tests for a Sinatra app that takes input from an API via a gem. Once I have the API response I need to test that the template has correctly rendered. The response of the API will be the HTML of the page that I am loading.
My first instinct was to write a test that looks like this:
describe 'the root path'
it 'should render the index view' do
get '/'
expect(last_response).to render_template(:index)
end
end
Unfortunately when I try this I get the following error: undefined method `render_template'
I was wondering if anyone has encountered this problem - it seems like it should be an easy fix, but I can't seem to find any documentation to help with it.
I'm currently not testing views at all because of time constraints, but I did have some limited successs with Rack::Test.
In theory you can say:
require 'rack/test'
include Rack::Test::Methods
def app
Sinatra::Application
end
describe 'it should render the index view' do
get '/'
expect(last_response).to be_ok
expect(last_response.body).to eq(a_bunch_of_html_somehow)
end
If I were to go this road again, since my views are haml, I could implement the a_bunch_of_html_somehow method using a call to Haml::Engine -- but I'm not sure whether that helps you.
I'm lifting this wholesale from the Sinatra site here -- the page is well worth a read.
We ended up scrapping this approach since it was better handled by integration testing tool suites such as Selenium or Capybara. There is no equivalent that I could find in the basic Sinatra Rspec suite that could do this - it made more sense to move it into a different scope
Using Chimp.js, Cucumberjs and WebdriverIO, I'm trying to run login step definitions in a browser instance, before other step definitions that depend on a user to be logged in. And possibly without adding them into the Background over and over again for each feature file.
Is this possible? I'm quite new to Wedbdriver.io and Cucumber and any advice would be a great help. Please let me know if more info is needed.
Personally I don't think this is a good idea. To log someone in you have to specify 'who' the user is. Later when your application becomes more complex you might have interactions between different users. Hiding any of this from the scenario is not good.
What you can do is combine user specification and login in single steps e.g.
Given I am logged in as an admin
Given Fred is logged in as a sales executive
etc.
If you are clever about how you implement these steps you can keep things fairly dry by extracting helper methods from the step definitions and using global variables to store people e.g.
Given 'I am logged in as an admin' do
#i = create_user role: admin
login as: admin, user: #i
and reuse these methods in other login steps.
If you organise your features well, you can background alot of these calls e.g.
Feature: Basic admin ops
Background:
Given I am logged in as an admin
Scenario: I can foo
When I foo
Scenario: I can bar
When I bar
Some final thoughts ...
Each scenario is there to drive a particular piece of development. Compared to the work of doing the development writing "Given I am logged in" is trivial.
When something goes wrong knowing that you were supposed to be logged in is an essential piece of information.
I've been looking for ways to test a Rails 3 app that has quite a lot of JS code for its rich interface. I tried with Capybara, but that didn't work out, so now I'm giving Jasmine a try. But I'm having a hard time understanding how I should go about it.
From what I gathered, Jasmine alone is good for testing the JS components of a site, but what if I want to test the interface directly? I need something like:
describe "Sign in"
Visit '/home'
When user clicks "Sign in" link
The sign in form should appear
Can I actually do something like that with Jasmine? So far, my tests are included on a results page generated by the rails-jasmine gem and obviously they run over that DOM, not over my site's DOM.
I'm now trying to use evergreen, but I get the same result (I can't even include jQuery).
Any ideas?
Thanks!
To answer your question - no, Jasmine will not inherently function in a way which will let you navigate your site and test at such a high level, like an integration test with Cucumber.
Jasmine is built primarily to test the API of your js, and so essentially you will only be able to test URL routes or something with it if they are part of your API.
For example, you can test how a Backbone Router will respond to your window's current location, or navigating from one location to the next, but that is because Backbone Routers explicitly handle URL locations.
This might help: http://railscasts.com/episodes/275-how-i-test
You could try using jasminerice with fixtures. If the intent is to test the JS DOM interaction, then fixtures would be the way to go.
But if the idea is to test the server interactions as well, then going with something like cucumber makes sense.
I'm trying to automate my database population with sample objects, so I use rake tasks. I would like to use some data from other website pages.
I created txt file with url list from where that information supposed to be read and ran into problem: I don't know how to make requests outside from rake task. I need to get response, extract some selectord as RSPEC allows to do. Thank you, guys!
For custom rake tasks, you can always create your own plugin. Refer rails guide - plugins section.
In the plugin, you can use get method to get the data from an external URL. Refer ActionDispatch::Integration::RequestHelpers methods for the details.
You can add your own extraction logic and seed the database.
I am doing my first baby steps with Rails (version 3) now. I'd like to create a simple app catching data from the twitter/instagram/ API. Thankfully there are already gems doing the heavy lifting with connecting to the services, providing the data. Now I wonder what the best-practice is to add this functionality to Rails correctly.
My feeling is the best way is to create a new non-DB Model for each service I want to include and create some scopes, which I will then use in the controller. The scope definition includes the functional code, instantiating and using the twitter/instagram gems to get the web service's data.
Is this model/scope approach right or did I miss something?
In future I might need to cache all the fetched data to handle common API request limitations. Is there any good approach for this?
I'd appreciate your thoughts or examples/resources on this topic.
I think in this situation a standard class would be ok e.g.
class TwitterImport
def get_tweets
# Download tweets
...
# Create tweets
Tweet.create(.....
end
end
I created something similar recently. I created a folder called scripts in my app directory and stuck a class in there called import.rb. Because this file lives within the app directory it automatically has access to the Rails goodness i.e. existing Models etc.
I then set it up as a rails runner script, you run it via teh console from your app's root directory:
rails runner -e development TwitterImport.get_tweets