Jasmine: testing my rails site's interface with it - ruby-on-rails-3

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.

Related

Sinatra Rspec - testing that a view has rendered

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

how to interact with javascript JSON response with rspec and capybara

I'm using rspec and capybara and would like to test a JSON response that I get in response to for example click_button. I understand that I can use :js => true but I would like to parse back the JSON that I get. I see that I can do something like:
get '/your/path', format: 'js'
Is there a way to do something like:
click_button('Save', format: 'js')
::JSON.parse(response)....
?
thx
The aim of browser elumation libraries like Selenium is to approach real browsers and allow emulating behavior of real users. Real users can't read responses to AJAX actions so browser emulation libraries don't give such ability. Also it will be quiet hard for Selenium guys to implement it.
There are several possibilities that you have:
Write this test using one of http client libraries. But you can't really test end-to-end something that involves lots of Javascript and AJAX using this method
It's likely that AJAX action changes something in the DOM of your application. You can easily write a check for it using Capybara.
But if really want to test your app end-to-end and want to directly check HTTP response to AJAX action you should use a proxy that will record all responses. Then you make a search through those responses. Selenium maintainers advice to use Browsermob proxy to do something like this. Here are Ruby bindings for it that are written by a maintainer of Selenium's Ruby bindings
I had to do this for a special use case as well.
You can strip the html tags and parse it:
JSON.parse(ActionView::Base.full_sanitizer.sanitize(page.html))

What should I test in views?

Testing and Rspec are new to me. Currently I'm using Rspec with Shoulda and Capybara to test my application. It's all fine to test models, controllers, helpers, routing and requests. But what should I exactly test in views? Actually I want to test everything in views, including DOM, but I also don't want to overdone things.
These three things would be a good starting point
Use Capybara to go start at the root of your site, and have it click on links and whatever until it gets to the view you want tested.
Make sure what ever content is supposed to be on the page, is actually showing up on the page. So, if they 'user' went to the Product 1 page, make sure all the Product 1 content is actually there.
If different users see different content, make sure that's working. So, if Admin users see Admin-type buttons, make sure the buttons are they when the user is an Admin, and that aren't when the user isn't.
Those 3 things are a pretty good base. Even the first one is a big win. That will catch any kind of weird view syntax errors you may have accidentally introduced, as the syntax error will fail the test.
At my work we are using RSpec only to do unit testing.
For business testing or behavior testing we are using Cucumber that is much more readable for the business and IT guys.
It's like a contract that you sign with your business or it's like a documentation that you can execute.
Have a look at Cucumber: http://cukes.info/
I use view specs to verify that the view uses the IDs and classes I depend on in my jQuery code.
And to test different versions of the same page. E.g.:
I would not want to create two full request or feature specs to check that a new user sees welcome message A and a returning user welcome message B. Instead I would pick one of the cases, write a request or feature spec for it, and then a additional view spec that tests both cases.
Rails Test Prescriptions might be interesting for you, since it has a chapter dedicated to view testing.

Injecting arbitrary Javascript on all my Rails view

I'm trying to implement a javascript tracker that i need to inject arbitrarily on all of the views rendered by my application, just like the newrelic client instrumentation works.
My app allows user to edit their liquid html templates, so the idea doing this is to inject the script in a way that the user is uncapable to remove it (auto added)
I look the code in the newrelic gem but is too confusing and i wondering if there is a more simple way to do it.
Thanks in advance!
Well I have a solution for this you could write a middleware where you could just check
if the request is for html page or (css or javascript)
if the request is for the html page
append the javascript to the html page before sending the response for the server
here the catch you need very sure what you are doing this I have ran into this problem
Make sure your middleware placement is correct since the development everything is single thread and wrong placement would result in deadlock error
When HTML page is consider what if the request is an ajax request what then you have to be very specific on that regards
Hope This help

How might I provided a URL use the FireShot API to take a screenshot, upload to Imgur, and return some output (eg. markdown)

I am looking for a way to utilize the FireShot API with JS to given a URL (or perhaps a list) use the FireShot API to take screenshot, upload to Imgur, then return the user the URLs or perhaps something like markdown to use quickly in forums.
Method 1: Open new window
I tried opening the URL in a new window, but found that I cant control that page with JS dues to cross domain problems. The same with iFrames.
Method 2: simple $.get()
A simple $.get() wont work because of the same cross domain issues I guess?
http://jsfiddle.net/t6aeq/
$.get($url.val(), function(data) {
console.log(data);
});
Via PHP "Proxy"
So I tried creating a simple PHP script that gets the HTML of the URL and returns it to my JS (using file_get_contents($url)). But some sites like Microsoft will detect that I am using some automated methods and give an error page of sorts. I also cant seem to find a way to use jQuery to query that returned HTML for link[rel=stylesheet], script, style and body to append to the head and a div respectively. I posted abt that on another question
A new Idea: Embed scripts on browser level
So I thought away of getting around these is using iMacros or GreeseMonkey or something to insert scripts into pages on the browser level instead? But any guidance or tips on how can I do that? Also, I'd prefer a pure JS/PHP method if available so users are not limited to using Browser plugin/scripts (tho I will be the only user for now)
It suddenly came to my mind that this may not work because the FireShot API key and Imgur is limited to the domain? Any solutions?
You might be able to inject the FireShot script using Greasemonkey. But, first use GM_xmlhttpRequest() to fetch an API key, for that page's domain, from the "Create FireShot API Key" page.
Note that GM_xmlhttpRequest() does not have the same cross-domain issues that $.get() has.
However, at this point you might be better off just writing your own Firefox add-on. Maybe start with FireShot's code for ideas. Also see the Screengrab add-on.