How To Drive Out AJAX Functionality in a Rails View

I am new to RSpec and have just started to drive out my first Rails view
using a spec. I have used the The RSpec Book (beta) to do the basic
stuff like testing for the presence of a field but I am unsure where to
start for driving out some AJAX functionality.

In the view, I will have a text field that a user can enter a name into
and then click on a link to check the availability of this name or
otherwise. I plan to implement the check as an AJAX request, returning
an HTML snippet or ‘available’ or ‘not available’.

I would appreciate some help on what sort of examples one might write
and the various mocks, stubs and helpers etc that can be used. Or
alternatively a pointer to some existing information/tutorials on this
topic.

Thanks.

mobile: +44(0)775 392 8067
home: +44(0) 208 8358256
email: [email protected]

Lee L. wrote:

I am new to RSpec and have just started to drive out my first Rails view
using a spec. I have used the The RSpec Book (beta) to do the basic
stuff like testing for the presence of a field but I am unsure where to
start for driving out some AJAX functionality.

In the view, I will have a text field that a user can enter a name into
and then click on a link to check the availability of this name or
otherwise. I plan to implement the check as an AJAX request, returning
an HTML snippet or ‘available’ or ‘not available’.

gem install nokogiri rkelly assert2

require ‘assert2/rjs’

specify ‘a simple passing assertion works’ do
xhr :get, :xhr_availability, :name => ‘masone’
js = @response.body
js.should send_js_to(:replace_html, ‘label_7’, /available/)

 js.should send_js_to(:replace_html, 'label_7'){
             span /available/
             }

end

The first send_js_to just checks for a regexp to match the payload of
the
Element.update call. The second one uses {} to generate a Nokogiri
Builder
snippet of HTML, and match that. Here it’s just span, but it could have
been
more complex HTML. Google assert_xhtml for more on that.

I would appreciate some help on what sort of examples one might write
and the various mocks, stubs and helpers etc that can be used. Or
alternatively a pointer to some existing information/tutorials on this
topic.

The RSpec community, in my exalted opinion, mocks too much! If you can’t
use the
real thing, it’s too coupled, so break it up!


Phlip
http://flea.sourceforge.net/resume.html

Lee L. wrote:

I am new to RSpec and have just started to drive out my first Rails view
using a spec. I have used the The RSpec Book (beta) to do the basic
stuff like testing for the presence of a field but I am unsure where to
start for driving out some AJAX functionality.

To test the onchange=‘’ of the field, start by pulling in the Test::Unit
versions of the assertions:

Spec::Runner.configure do |c|
c.include Test::Unit::Assertions
end

Now use assert_xhtml to grab your edit field and return it as a Nokogiri
node.
This line does it for a All:

 a = assert_xhtml{|x|  x.a 'All', :href => '#'  }
 assert{ a[:onclick] =~ /new Ajax.Request.*xhr_run_all/ }

.send_js_to is supposed to work in the second line, but I have not yet
researched out how get rkelly to parse the Ajax.Request line.

The point of using rkelly inside send_js_to (aka assert_rjs_) is it’s a
real
JavaScript lexer, not a Regexp, so when I get it working it will be very
accurate!


Phlip
http://flea.sourceforge.net/resume.html

On Tue, May 12, 2009 at 8:33 AM, Phlip [email protected] wrote:

HTML snippet or ‘available’ or ‘not available’.
js.should send_js_to(:replace_html, ‘label_7’){
the various mocks, stubs and helpers etc that can be used. Or alternatively
a pointer to some existing information/tutorials on this topic.

The RSpec community, in my exalted opinion, mocks too much! If you can’t use
the real thing, it’s too coupled, so break it up!

Phlip,

You could just say “be careful not to mock too much,” which would be
really good advice, but instead you make a generalizing and judgmental
statement like this. When’s the last time you paired with someone in
the RSpec community?

Lee,

Phlip has some really great ideas about some things, and assert2 is
lovely, but based on several posts on this and other lists, I’d say he
doesn’t really like RSpec, nor understand its underlying intent. So by
all means listen to his advice, and by all means take advantage of
assert2 for this particular problem, but please also understand that
he is in no way the voice of the RSpec community.

Cheers,
David

On May 12, 2009, at 8:36 AM, Lee L. wrote:

I am new to RSpec and have just started to drive out my first Rails
view using a spec. I have used the The RSpec Book (beta) to do the
basic stuff like testing for the presence of a field but I am unsure
where to start for driving out some AJAX functionality.

Check out Adam McCrea’s fork of webrat:

It includes a submit_form_via_ajax method that I use to do this. It
basically just forces Rails into treating the form request as asking
for a .js response. There are limitations on what you can do with the
response (e.g. inspecting the entire page is no longer possible), but
you are able to look at the response body of the call and match it
against regular expressions. So, I use features like:

 When I go to the homepage
 And I use a search term of "foo"
 And I press "search"
 And the edit_search_form is submitted via ajax
 Then the search results should have 2 bars

with the critical step like:

When /^the (.+) is submitted via ajax$/ do |form|
submit_form_via_ajax form
end

I’ve left out a couple of things here (in particular, a step that
fills in form fields to mimic javascript action), but this basic idea
makes it possible to have acceptance tests for ajax based features
that are written in the language of the customer and yet operate
quickly (i.e. you don’t need to have selenium or something else like
that involved to run this).

The drawback of course is that it’s not really exercising the full end-
to-end system. While I understand that this is frowned upon (and for
good reason), in my case, I have decided that the speed of the tests
(and thus my willingness to use them) makes up for the drawbacks
involved. To limit my exposure, I’m working on including javascript
unit tests that will ensure that the behavior I stub out above
actually works as expected.

Mike D.

On 12 May 2009, at 15:07, David C. wrote:

David
Lee,

One thing you might want to consider is looking at using a headless
browser like ‘celerity’ for testing your ajax code. This is quite a
bit more involved for initial setup than using RSpec but will give you
real confidence as you’re actually running your javascript inside a
browser. There are quite a few people on this list who are doing this,
using the ‘progressive enhancement’[1] pattern to build a version of
the page that works with raw HTML, then decorate it with javascript
behaviour when the page loads.

I’m not doing this myself in earnest, so I’ll say no more, but
hopefully a couple of other people will chime in with some advice.

[1]Progressive enhancement - Wikipedia

Matt W.
http://blog.mattwynne.net

Thanks Philip.

I should have added in my original post that I have included the
Webrat::Matchers as instructed in The Rspec Book.

Unless I have misunderstood you, it appears that RSpec with
Webrat::Matchers do not support the driving out of AJAX functionality
in views, hence the need to use Nokogiri. Is my understanding correct?
Or is this your preferred approach but there are others?

Thanks Matt.

I have been trying out Cucumber and Culerity (Celerity) but rather
than jump directly from Cucumber to coding the necessary views,
controllers and models required for each scenario, I wanted to drive
out the code using RSpec. So I’ve started to spec a view required by a
scenario, and this is where I am confused about how I approach the
AJAX aspects of the view in my specs.

Thanks Mike.

fyi, I am trying out Cucumber and Culerity for integration testing.
Culerity provides for AJAX testing.

Having written my first Cucumber (with Culerity) feature and set of
scenarios, I was keen to then use RSpec to begin driving out the
views, controllers etc so that I can eventually run the e2e Cucumber
scenarios.

David C. wrote:

You could just say “be careful not to mock too much,” which would be
really good advice,

Sorry; I thought I said that. This industry in general dislikes strong
opinions…

Mock on, everyone!

but instead you make a generalizing and judgmental
statement like this. When’s the last time you paired with someone in
the RSpec community?

Well it’s not for want of trying!


Phlip
http://flea.sourceforge.net/resume.html

I found a potential solution from this blog:
http://www.rubytutorials.net/2008/02/29/small-rspec-revelations-rjs/

In my spec for the view in which I want to include the AJAX
functionality (“new.html.erb_spec.erb”), I have added a couple of
Examples to drive out the some of the AJAX functionality:

it “should render /Available/ if name does not exist” do
@name_exists = false
assigns[:name_exists] = @name_exists
render “contexts/check.js.rjs”
response.should have_rjs(:chained_replace_html, ‘checkname’) do
response.should have_text(/Available/)
end
end

it “should render /Not available/ if name does not exist” do
@name_exists = true
assigns[:name_exists] = @name_exists
render “contexts/check.js.rjs”
response.should have_rjs(:chained_replace_html, ‘checkname’) do
response.should have_text(/Not available/)
end
end

The rendered template “check.js.rjs” contains:

if @name_exists
page[‘checkname’].update(‘Not available’)
else
page[‘checkname’].update(‘Available’)
end

These examples pass and seem to achieve my objective of using the spec
to drive out the required AJAX behaviour, or at least some of it.
Though I suspect that this approach may have limitations for other
types of AJAX functionality.

At this stage, I am wondering whether it is worth trying to drive out
any AJAX functionality at the point of writing RSpec view specs. Some
replies seem to suggest the use of Cucumber with Culerity/Webrat/
Selenium and I read into this that one would bypass view specs for the
AJAX related steps and just write the necessary view code (e.g.
JavaScript or Rails Prototype helpers) to get the step to pass.

Further thoughts appreciated.

Thanks Lee.

Hi–

On May 13, 2009, at 12:47 AM, Lee wrote:

I found a potential solution from this blog:
http://www.rubytutorials.net/2008/02/29/small-rspec-revelations-rjs/

In my spec for the view in which I want to include the AJAX
functionality (“new.html.erb_spec.erb”), I have added a couple of
Examples to drive out the some of the AJAX functionality:

The one thing I would add is that Rails responds differently when it
receives a post with XMLHttpHeaders than when these headers are not
present. I typically put this in my spec_helper.rb and then I can
include it where necessary.

spec_helper.rb

module XmlHttpHelper
def set_xhr_headers
request.env[‘HTTP_ACCEPT’] = ‘application/json, text/javascript, */
*’
request.env[‘HTTP_X_REQUESTED_WITH’] = ‘XMLHttpRequest’
end
end

things_controller_spec.rb

describe ThingssController do
include XmlHttpHelper

   it "should provide a not acceptable response if user is not

appropriately related and it’s an xhr" do
login_as(@unrelated_child.login, ‘secret’)
set_xhr_headers
post :slug_collection, :name => ‘bob’, :collection_name =>
‘my-things’
response.status.should eql(‘406 Not Acceptable’)
end
end

Just a thought…

On 12 May 2009, at 16:33, Lee wrote:

Thanks Matt.

I have been trying out Cucumber and Culerity (Celerity) but rather
than jump directly from Cucumber to coding the necessary views,
controllers and models required for each scenario, I wanted to drive
out the code using RSpec. So I’ve started to spec a view required by a
scenario, and this is where I am confused about how I approach the
AJAX aspects of the view in my specs.

If you’re using progressive enhancement though, I wouldn’t expect the
views themselves to be any different - the code to add javascript
behaviour is all in external js files. I’d personally recommend doing
that over using the rails js generators that squirt behaviour into
your onclick events. eugh.

behaviour when the page loads.
[email protected]://rubyforge.org/mailman/listinfo/rspec-users


rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

Matt W.
http://blog.mattwynne.net