Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stubbing outgoing requests from Rails server #92

Open
andretgregorio opened this issue Dec 14, 2021 · 14 comments
Open

Stubbing outgoing requests from Rails server #92

andretgregorio opened this issue Dec 14, 2021 · 14 comments

Comments

@andretgregorio
Copy link

Hello, there.

Thanks for writing and maintaining this lib. This is some awesome work.

I'm currently trying to integrate it with my Rails app, and I've found a situation that I don't know how to work around.
My Rails app has to call some 3rd party services using standard HTTP requests. In our tests that run in rspec we can just stub those requests and provide the response body we want. But since with Cypress I'm running my application in an environment that is not rspec, is there a way to stub outgoing requests from the Rails server?

This is an example where an outgoing request is being stubbed for regular tests:

shared_context 'when using ViaCEP' do
  before do
    stub_request(:get, %r{https://viacep.com.br/ws/.*/json})
      .with(headers: { 'Host' => 'viacep.com.br' })
      .to_return(status: 200, body: viacep_response.to_json)
  end

  let(:viacep_response) { build(:viacep_address) }
end

Regards.

@andretgregorio andretgregorio changed the title Stubbing requests from Rails server Stubbing outgoing requests from Rails server Dec 14, 2021
@grantspeelman
Copy link
Collaborator

Unfortunately this is not something that is possible currently. This is very similar request to #39 that would like to use VCR.

Closest I can give you to a solution is what we do at my company.
We basically create gem wrappers around any third party services that needs to be interacted with, then we add a "test mode" to the gem, which basically just returns hard coded results.

Here is an example of one of our gems where we wrote a faraday adapter that just reads the response from a file:
https://github.com/NEXL-LTS/ms_graph_rest-ruby/blob/main/lib/ms_graph_rest.rb#L20

But hopefully one day someone figures out how we could do stubbing or VCR.

@MUTOgen
Copy link

MUTOgen commented Dec 15, 2021

Hey @andretgregorio @grantspeelman
I'm working on exact same problem, and I'd like to make it possible to use VCR for that purpose.
I pushed my draft here #93
Please, feel free to comment

@mmbarness
Copy link

Curious about what progress has been made on this! Haven't used VCR, but I like the way it seems to work, and I definitely need some way of stubbing before I'm able to implement cypress-on-rails at work.

@mlabarca
Copy link

mlabarca commented Mar 7, 2022

It would really be great to see #93 getting merged in some form, this is still a bit of a pain

@mmbarness
Copy link

^^^^^^

@grantspeelman
Copy link
Collaborator

grantspeelman commented Mar 8, 2022

Be good if someone can give the new feature a test :)

https://github.com/shakacode/cypress-on-rails#expermintal-features-matching-npm-package

It's not released as a version yet , so make sure to point your Gemfile at github
hopefully following the instructions in the README will get you setup.

  gem 'cypress-on-rails', '~> 1.0', github: 'shakacode/cypress-on-rails', branch: 'master'

@mlabarca
Copy link

mlabarca commented Mar 8, 2022

Oh wow I can't believe I missed this 🤦‍♂️ I'll point the gem to Master and add the npm package in a bit, thanks! Maybe we should just close the other pr?

@mlabarca
Copy link

mlabarca commented Mar 8, 2022

Alright, I spent a couple hours testing this and it wasn't working as well as I hoped. The only way i got this to reliably work was using a setup like this using wait:

  beforeEach(() => {
    visit('some url');
  });

  it('creates the integration and move to the next page with jobs', () => {
    cy.vcr_insert_cassette('external_systems-valid', {
      record: 'new_episodes',
    }).as('casette');
    cy.get('@casette').then(_response => {
      // Do some stuff that makes requests in the backend app
      cy.vcr_eject_cassette();
   });

Before putting the code in a wait like this I'd sometimes get two cypress VCR insert requests to the server (which would fail the test), and sometimes it'd write the request to casette, sometimes it wouldn't etc. This is my vcr setup on cypress_helper:

require 'vcr'
VCR.configure do |config|
  config.hook_into :faraday
  config.after_http_request(:real?) do |request, response|
    puts "Unhandled Cypress VCR Request:#{request.uri}"
    puts "#{request.to_hash}" # or request.body
  end
  config.allow_http_connections_when_no_cassette = true
end 

The extra logging made me notice it still seems flaky regarding where it picks up stubbs in the yaml, but this could be an issue with faraday. I'm on cypress 6.2.1 and chrome 98 headless.
It would be great if someone else tested it as well before releasing.

@mmbarness
Copy link

I'm planning on getting into it, hopefully this week

@grantspeelman
Copy link
Collaborator

grantspeelman commented Mar 9, 2022

@mlabarca can you check if you starting the server with only 1 process, ie if you are using puma you can only have 1 worker.
I might have to make a note of that in the README

@grantspeelman
Copy link
Collaborator

Did some more testing myself as well, and seems VCR only works well when doing single worker and single thread.

I have made some updates to the README and updated the code to turn VCR on and off between inserts and ejects.

Please let me know if you get better results with the updates and using puma in single worker and single thread mode.

@mlabarca
Copy link

@grantspeelman Hey there, I tested changing things with puma and effectively starting puma with 1 worker and 1 thread improved this and made this behave as standard as vcr in rspec. But after i upgraded to the last commit (b0311e7) VCR seems is not picking up my configuration in cypress_helper.rb; so instead of hooking into faraday, it's hooking into webmock and not allowing requests with no casette go through, so tests are now failing due to requests that were supposed to pass 😮 . Downgrading to the commit before solved it.

@grantspeelman
Copy link
Collaborator

cool, i'll update the code to only enable and disable webmock if that is what VCR is hooked into.
thx for all the help @mlabarca

@grantspeelman
Copy link
Collaborator

@mlabarca & @mmbarness & @MUTOgen & @andretgregorio i started a discussion #106 around this issue and would love your input on this and how you currently working around this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants