miragejs / miragejs

A client-side server to build, test and share your JavaScript app
https://miragejs.com/
MIT License
5.38k stars 168 forks source link

Cypress Intercept and Wait Timeout #1065

Open mdbiscan opened 1 year ago

mdbiscan commented 1 year ago

I've walked through setting up Mirage with Cypress and it seems to be working correctly. My app loads, makes its API calls, I can follow the path through the Cypress handler into Mirage.

My application is a browser app that communicates with physical devices on an ATM machine through local API and remote API for all our products and services. It is loaded in a browser on an ATM machine, but hosted on a remote server. It can turn on a device on the machine (like a bill collector or barcode scanner) via an API call to a device server on the machine. Then the browser listens on a WebSocket port for updates from the device as customers insert their money or scan barcodes.

For testing purposes, I've created virtual devices set up with MockSocket to send data to the socket manually when needed. Both the device and remote API base URLs are the same in test and development environments to simplify using Mirage. This has worked great for manually QAing on our dev machines and testing with Jest.

When it comes to end-to-end testing with Cypress, the timing is much trickier. I need to wait for the API call to turn on a device, then have the device send a message via WebSocket, using cy.wait and cy.intercept, but it seems that using Mirage is causing an issue with the alias never being called.

My test looks something like this:

  it('scans a barcode', () => {
    cy.intercept({
      method: 'POST',
      url: '/device/startBarcodeReader',
    }).as('startBarcodeReader');

    cy.intercept({
      method: 'POST',
      url: '/device/stopBarcodeReader',
    }).as('stopBarcodeReader');

    cy.visit('http://localhost:3000');

   // initialize app process
   // click through screens 

    cy.wait('@startBarcodeReader').then(() => {
      BarcodeReader.on();
    });

    // rest of the test
});

The alias @startBarcodeReader times out, but I can see in the Mirage logs that the API request has been made.

The log:

Mirage: [200] POST /device/startBarcodeReader

The error:

Timed out retrying after 5000ms: cy.wait() timed out waiting 5000ms for the 1st request to 
the route: startBarcodeReader. No request ever occurred.
maapteh commented 1 year ago

I guess its more or less the same as the service worker api MSW (so compared to mirage it shows the requests in the network tab etc). This also doesn't work with the traditional Cypress wait. For that library they created own handlers inside https://github.com/deshiknaves/cypress-msw-interceptor

I guess this miragejs should do the same and expose own handlers for it since they are using pretender.

Mirage uses Pretender.js which works by monkey-patching window.fetch and window.XMLHttpRequest.

albuquerquecesar commented 1 year ago

Hi @mdbiscan . Check this issue answer maybe it could help you.