0

I want to test a feature that in my app sends the usera custom message when a Rails UJS/ajax times-out.

The code to timeout the Rails UJS request is itself on the app:

$.rails.ajax = function(options) {
      if (!options.timeout) {
        options.timeout = 10000;
      }    
      return $.ajax(options);
    };

When observing on chrome dev tools what happened when it timed out on my local dev mode, I notice the code status is strangely 200 but as it "times out", my message is indeed displayed to the user.

on('ajax:error',function(event,xhr, status, error){
        // display message in modal for users
              if(status == "timeout") {
                console.log( ' ajax request timed out');
                var msg;
                msg = Messenger().post({
                  hideAfter:  8,
                  message:    "Too long, the app timed out"
                });
              } 
            }             
          });

Below is my current test (using puffing bill gem). I managed to stub the http response for my ajax request but I don't know how to tell rspec to "wait" and timeout like take 11 seconds and still not send any response to the xhr call:) (xhr max timeout is set to 10 000 milliseconds above so 10 sec<11sec, it should time out inside the rspec test)

it " displays correct modal message appears  correctly when xhr call timeout" do
  visit deal_page_path(deal)    
  proxy.stub("http://127.0.0.1:59533/deals/dealname/ajaxrequest").and_return(:code => 200)
  first('a.button').click 
  wait_for_ajax
  within('ul.messenger') do           
    expect(page).to have_content('Too long, the app timed out')
  end
end
Mathieu
  • 4,587
  • 11
  • 57
  • 112
  • Perhaps the timecop gem is what you are looking for? https://github.com/travisjeffery/timecop – Dan Rubio Jun 14 '16 at 18:53
  • i don't think i need to jump in time. i'm ok to wait the 11 secinds for the request. in which extent couldi use timecop? – Mathieu Jun 14 '16 at 21:04

1 Answers1

2

If you really want it to just wait for the timeout I believe you can use the Proc version of and_return and sleep for as long as you want the request to take

proxy.stub("http://127.0.0.1:59533/deals/dealname/ajaxrequest").and_return(
  Proc.new { |params, headers, body|
    sleep 11
    {code: 200}
  } )

also - rather than wait_for_ajax just pass the amount of time you expect the element to take to appear to the within call

within('ul.messenger', wait: 11) do ...
Thomas Walpole
  • 48,548
  • 5
  • 64
  • 78
  • genius. btw it did not work with "within('ul.messenger', wait: 11) do ." but only with "using_wait_time 12 do within('ul.messenger') do..." I don't know why – Mathieu Jun 16 '16 at 15:35
  • @Mathieu -- Glad it's working. Would the within call work with wait: 12 ?? Maybe 11 seconds was just too short - if not then it means the default wait is probably too short for have_content, you can set that time by passing a wait: option to it too - or just use the using_wait_time method as you have – Thomas Walpole Jun 16 '16 at 18:11
  • :) actually i use 12 sec in all the cases. the only situation it works is with using_wait_time 12 (all the other permuations fail including within('ul.messenger', wait: 12) do ... – Mathieu Jun 16 '16 at 18:14
  • 1
    ok - so that probably means its the have_content that you're actually getting the error from -- so you could have specififed wait on the have_content as well `expect(page).to have_content('Too long, the app timed out', wait: 12)` - but since you want the same wait time for both calls the `using_wait_time` is probably best – Thomas Walpole Jun 16 '16 at 18:16