Skip to content

Full Network Layer Stubbing / fetch support #687

Closed
@brian-mann

Description

@brian-mann

Pull Request (in progress): #4176

What users want

  • To be able to stub any kind of HTTP request including window.fetch
  • To blacklist certain domains (google analytics, new relic, intercom)
  • To have more control over dynamically routing / stubbing requests and responses
  • To more easily stub graphQL calls

What we do now

  • We modify the host XMLHttpRequest object which limits us to only stubbing XHR's from the main application frame.

What we need to do

  • Throw away the entire existing system for stubbing
  • Move stubbing into the internal Cypress network proxy layer (outside of the browser)
  • Synchronize the state of the browser tests with the backend (so its aware what needs to be stubbed / routed)
  • Remove cy.server and instead just use cy.route
  • Expand the API's for more advanced configuration
  • Accept blacklistDomains option for cypress.json
  • As each request comes in, if we expose callback functions we'll need to constantly communicate with the driver for guidance on what to do - whether to proceed - halt, etc. This can get pretty complicated and might have significant performance issues. We'll need to experiment and we may not be able to provide callback functions anymore.

Things to consider

  • onRequest and onResponse currently provide the raw level xhr object. This would no longer be possible. We'd have to serialize the request / response into basic objects. No method calling would be available.
  • The onError callback could no longer exist
  • Additionally we hook into the onerror events for XHR's and will automatically fail the test if this is called. This would no longer be possible.
  • Blacklisting https cannot be dynamic. It would have to be set in cypress.json or environment variables. The reason is that for each blacklisted domain that goes over https, we would have to route that traffic to a self signed certificate. Browser freak out if traffic to https gets assigned one certificate, and then within the same session it gets another cert applied. What this means is that before spawning the browser we have to isolate that traffic and know ahead of time not to route it to the actual server. This enables us to send a single cert to the browser.
  • We could enable non https hosts to be dynamically blacklisted, but these API's would be async and likely difficult for users to understand / use. We might be able to bake these into cy.route but I'm not sure there's much of a use case here of only dynamically blacklisting non https traffic.
  • We will no longer be able to tell the difference between an XHR and any other kind of http request. We'd likely have to change the page events to say REQ and REQ STUB instead of XHR and XHR STUB.
  • It would be very difficult to provide accurate onResponse callback functions. It's possible for the internal server to know when an HTTP request has been completed, but it's not possible to know whether the browser has actually finished processing it. This may or may not be a problem.
  • How would we handle stubbing binary / streaming responses?
  • How would we handle stubbing things like images? (This is likely pretty simple)

Bonus Points

  • It would likely be possible to stub Websocket traffic in the same manner
  • The problem with this is that most Websocket libraries (ie socket.io) add their own "encoding" pattern on top of each websocket message frame. The ergonomics around stubbing this would be odd. The problem is this is library (and even version of library) specific. This may be a better use case for cy.stub, or perhaps a 3rd party extension

Metadata

Metadata

Assignees

Labels

EpicRequires breaking up into smaller issuespkg/https-proxyThis is due to an issue in the packages/https-proxy directorytopic: networktype: featureNew feature that does not currently exist

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions