0

Within a rails app, I have an image (image_submit_tag) on a page that, when selected, sends an ajax request to server. The server receives the request, Does The Right Thing and responds with correct javascript. The correct javascript replaces one image with another. All of this works outside of cucumber/capybara/webkit environment. In other words, for humans.

When I exercise same as a single test (feature) of a rails(3.2.9) app under cucumber(1.3.9)/capybara (2.1.0) using webkit (capybara-webkit 1.0.0) tagged with @javascript I see different results.

Within test env, the response javascript is not getting evaluated by webkit. Instead, within a subsequent step that attempts to find new icon on the page, when I dump page.html all that is reported is the javascript response. That is, the page contains only the returned javascript.

Here is the step that is supposed to be able to see new content (It differs from above description because I have simplified response javascript in attempt to eliminate possibility of js errors).

Then(/^the "(.*?)" icon should be displayed$/) do |icon|
  puts "------------------icon display on page------------------"
  puts page.html
  puts "________________________________________________________"
  puts "************* icon displayed response headers ***"
  put page.response_headers.inspect
  puts "*************************************************"
  page.should have_content("some text")
end

I described output of page.html above, but the response headers add to the puzzle. For some reason, webkit (?) thinks there is something wrong with response.

bad URI(is not URI?): {"Content-Type"=>"text/javascript; charset=utf-8", 
  "X-Ua-Compatible"=>"IE=Edge,chrome=1", 
  "Etag"=>"\"e7d3ccc2c53dd8e31d6f92d7dbb69dc0\"", 
  "Cache-Control"=>"max-age=0, private, must-revalidate", 
  "X-Request-Id"=>"776cf759cc343884091b5daec6a18587", 
  "X-Runtime"=>"0.048413", 
  "Server"=>"WEBrick/1.3.1 (Ruby/1.9.3/2013-02-22)", 
  "Date"=>"Fri, 08 Nov 2013 03:07:43 GMT", 
  "Content-Length"=>"47", "Connection"=>"Keep-Alive"} 
(URI::InvalidURIError)

Finally, here is actual javascript that is returned by rails, Like I said, I have stripped it to bare minimum.

$('#go_on_duty').parent().html("some text");

From looking around for answers, I will anticipate some questions:
1. Yes, I have set Capybara.javascript_driver = :webkit.
2. Yes, the feature is tagged as @javascript

So, does anyone know why the javascript would not be getting evaluated? I have a sneaking suspicion that I am missing something obvious, but my eyes have grown weary.

On a related note, I am only this far because I explicitly set Accept header in request to javascript. I could do this b/c I am using webkit (as below)

page.driver.header 'Accept', 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript'

Prior to adding above line, my request was arriving at server "as HTML" so I was not even getting partial.js.erb rendered. I am willing to live with above work-around for the time-being but I can't help but think the problems are related either, as in "I am overlooking some simple capybara/rails/cucumber config issue." Again, this is only an issue in test environment; interaction works as expected when human-driven.


Update:

In response to popular demand, here is partial that generates image_submit_tag

<%= form_tag(shifts_start_shift_path, :method => :post , :remote => true) do %>
  <%=image_submit_tag("go_on_duty_sign.png", :size=> "35x35", 
                                             :id => "go_on_duty", 
                                             :title=>"Go On Duty") %> 
<% end %>

Here is action code from relevant controller:

def start_shift
  @shift = current_staff.current_shift
  if !current_staff.on_duty?
    @task_assignments = TaskAssignment.where(:shift_id => @shift.id)
    respond_to do |format|
      format.js
    end
  end
end

And here is js single line (reproduced from above and, clearly, minimalized ) from start_shift.js.erb template used to render response:

$('#go_on_duty').parent().html("some text");

I hope this helps clear things up, but I would re-emphasize this all works when human-driven. I only see problem under test environment. Thanks...


Environment:

gem 'rails', '3.2.9'

group :test do
    gem 'cucumber-rails', '1.4.0'
    gem 'rspec-rails', '2.7.0'
    gem 'database_cleaner', '0.7.0'
    gem 'factory_girl', '2.3.2'
    gem 'capybara-webkit', '1.0.0'
end  
rkgordon3
  • 141
  • 1
  • 4
  • Can you paste real test code instead of all "puts"? – Billy Chan Nov 08 '13 at 04:29
  • The "real test code" is essentially the single page.should have_content("hello world") assertion. The point is that the page does NOT contain the changes to DOM expected by the evaluation of returned javascript but only the javascript itself. The puts were intended to indicate exactly how/where I am seeing the problem. – rkgordon3 Nov 08 '13 at 14:12
  • Sorry, I am really not able to debug with a block of text and a single assertion. – Billy Chan Nov 08 '13 at 14:39
  • See updates above. Thanks for looking at it... – rkgordon3 Nov 08 '13 at 16:09
  • A couple suggestions that might aid debugging: 1) try changing your driver from :webkit to :webkit_debug and 2) try using save_screenshot instead of dumping the page's HTML. – Joe Ferris Nov 10 '13 at 15:34
  • **SOLVED** It turns out the problem was vestigial prototype scripts. I solved the problem by (on a lark) switching to poltergeist. There I saw better javascript error reporting. That led me to investigate all project javascript (not just that related to request under scrutiny). When I removed obsolete prototype files, all was well and both webkit and poltergesit now run my tests without a hitch. – rkgordon3 Nov 12 '13 at 17:07

0 Answers0