1

I'm looking to stub requests made with JavaScript in testing an external webpage. Puffing-billy looks to be the way to go - here's the code:

describe 'Covetable click behavior' do
  let(:user) { create(:user) }

  describe 'clicking button', :type => :feature, js: true do
    it 'makes a request to our api' do
      visit 'http://externaldomain.com'
      allow_any_instance_of(Analytics::EventsController).to receive(:create)

      sleep(7) # may be race conditions at work; helps following test pass
      expect execute_script(typeof eventAnalytics == 'function').to eq true
      # testing that the javascript making the request is loaded

      proxy.stub('https://ourdomain/analytics/event').and_return(redirect_to: 'http://localhost:3000/analytics/event?name=$likeButtonClicked')

      click_button 'Like'
      expect_any_instance_of(Analytics::EventsController).to receive(:create)
    end
  end
end

Capybara.javascript_driver = :selenium_billy

config.around(:each, type: :feature) do |example|
  WebMock.allow_net_connect!
  VCR.turned_off { example.run }
end

Appreciate any suggestions for moving forward stubbing the requests!

Edit: updated the code, and added more in-depth logging.

The proxy stub doesn't raise an error directly, but does not intercept & redirect the http request being made. The test.log file either skips the request entirely or allows it: puffing-billy: PROXY GET succeeded for 'https://ourdomain.com:443/analytics/event...'

Failure/Error: Unable to find matching line from backtrace
   Exactly one instance should have received the following message(s)     but didn't: create`

I've also tried stubbing ourdomain.com:443, but it didn't seem to make a difference.

bjorn
  • 175
  • 2
  • 9

1 Answers1

1

Capybara controls a browser and then the browser makes the requests, runs the javascript, etc. Because of that you can't stub the responses in the tests with stub_request because the browser doesn't know anything about that, it's just making requests to the server app. You can use puffing billy to redirect the requests from the browser, you will however need to make sure the proxy is getting correctly set in the driver. You can either do that manually when registering your own driver instance, or use one of the puffing billy provided driver setups (see the puffing billy readme for :selenium_billy, etc)

Thomas Walpole
  • 48,548
  • 5
  • 64
  • 78
  • Thank your for the direction - I've been working on the puffing-billy config but have yet for puffing-billy to recognize and redirect the request. I've tried with both :selenium_billy and :selenium_chrome_billy as drivers for capybara. – bjorn Sep 22 '15 at 23:52
  • Are you sure its not redirecting, or are you saying that your expectation isn't succeeding? If the later - does create get called on a GET to that url? (redirects are only sent as GET requests - not POST that would normally be used for a create action) - If it really isn't redirecting at all -- please update the code in your question to exactly what you're now using - including where you're setting the capybara driver – Thomas Walpole Sep 23 '15 at 00:10
  • Yes, get requests are sent to events#create. Updated the code as you requested. – bjorn Sep 23 '15 at 01:32
  • Puffing-billy does an exact string match of the urls after stripping the query params (assuming you havent changed the default of strip_query_params) if passed a string - so it would have to exactly match everything prior to the ? You can also pass a regexp so maybe try proxy.stub(/ourdomain\.com/).and_return(...) just to make sure the matching is working – Thomas Walpole Sep 23 '15 at 03:07
  • Also. You're redirecting to port 3000 - That's normally people's dev server port not the port capybara runs its copy of the app on. If that's the case in your setup the expectation won't work and you need it to redirect to the app instance capybara starts – Thomas Walpole Sep 23 '15 at 13:50
  • Good point on the port - changed the redirect to `http://localhost:#{Rack::Server.new.options[:Port]}/...` I tried the regex as you suggested - when I manually click the button in the browser the request is stubbed, but is still not received by the controller action. Will test the routing some more on the test server - on development env the controller receives the request fine. – bjorn Sep 23 '15 at 17:19
  • I don't understand why you're starting a new rack::server? If you are trying to redirect to the server instance capybara runs then it would be "http://#{page.server.host}:#{page.server.port}..." – Thomas Walpole Sep 23 '15 at 18:05
  • Good point - set the redirect to your suggestion. Couple answers [here](http://stackoverflow.com/questions/1554267/how-to-find-the-local-port-a-rails-instance-is-running-on) were setting the Server.new. Unfortunately the request is still getting through the stubbing. – bjorn Sep 24 '15 at 22:27
  • Ok well I'm at a loss here -- You said that the proxy was stubbing the request when you manually click the button when using the regex, and then you corrected the host and port that it should be redirecting to - so that should be working correctly. But now you say its getting through the stubbing -- Sorry, I have no more ideas since I'm confused by the status you're reporting – Thomas Walpole Sep 25 '15 at 00:12
  • Sorry for being inconsistent there. The stubbing worked on manual clicks when I set the stubbing to /ourdomain\.com/. I'm looking through the puffing-billy source now to figure out why the matching isn't working otherwise. Will update when I figure it out. – bjorn Sep 25 '15 at 18:16
  • The stubbing is now working correctly. I believe the main thing I've done to get to this point is adding paths to the Billy config whitelist. Also, matching https requests requires adding port 443 to the stub (i.e. 'domain.com:443/'. The test is still failing due to a MissingTemplate error - I've posted a new question with updated info here: http://stackoverflow.com/questions/33024937/stubbing-requests-with-puffing-billy-or-webmock – bjorn Oct 08 '15 at 20:57