0


I have stuck with Cypress fixtures. Can't intercept an XHR request with SSR and navigation routing.

cypress/integration/page.js:

const fetch = require("unfetch")

describe("/about", () => {
  beforeEach(() => {
    cy.visit("/", { // Visit home page to trigger SSR
      onBeforeLoad (win) {
        win.fetch = fetch // replace fetch with xhr implementation
      },
    })
  })

  it("Has a correct title", () => {
    cy.server()
    cy.fixture("about").then(about => { 
      // about object is correct here, like {title: "About+"}
      cy.route("GET", "http://localhost:8080/api/documents/url", about) // Not sure where .route should be
      cy.get(".main > :nth-child(1) > a").click() // Navigate to the /about page
      cy.route("GET", "http://localhost:8080/api/documents/url", about) // Tried both ways
      // This hits my server API without stubbing, getting {title: "About"}
      cy.title().should("eq", "About+") // About != About+
    })
  })
})

cypress/fixtures/about.json:

{"title": "About+"}

I see an XHR request (type=xhr) in Dev Tools and it doesn't use the above about stub object but hits real API instead. Why? Double checked URL and method – 100% the same. Can it be that route is coupled to visit and ignores click-based routing?!

Ivan Kleshnin
  • 1,667
  • 2
  • 21
  • 24
  • I would try calling `cy.server()...cy.route()` before `cy.visit()`, that is certainly the documented pattern (see [Examples](https://docs.cypress.io/api/commands/route.html#Examples)). Likely the navigation routes are bundled, so that might not even help. What is the build system, and what exactly shows in the Ntework tab? – Richard Matsen Jan 31 '19 at 20:34
  • Maybe also need to use `cy.on('window:before:load', (win) => {...` pattern shown here [Window Before Load](https://docs.cypress.io/api/events/catalog-of-events.html#Window-Before-Load) so that you can do `cy.visit()` later in the sequence but still have fetch replaced earlier. (Not sue if this is absolutely neccessary). – Richard Matsen Jan 31 '19 at 20:42
  • 1
    This looks promising [mocking server for SSR react app e2e tests with cypress.io](https://stackoverflow.com/questions/47631821/mocking-server-for-ssr-react-app-e2e-tests-with-cypress-io). If I follow Linaco's answer correctly, the first test shows that `cy.route()` will not work with SSR. – Richard Matsen Jan 31 '19 at 21:23

1 Answers1

3

Rechecking this once again, I've found a solution. Let me share the details for everyone interested:

1) I use Next.js which is an excellent tool for SSR but it doesn't allow you to disable server-side rendering (yet) according to this and this issues.

2) You can use Cypress with SSR pages but, in this way, you're limited to testing real HTML. Which means you have to either couple tests to real data (not good in most cases) or stub the database itself (slow). In general, you want to stub HTTP requests.

3) Cypress can't stub fetch requests and mocking fetch with XHR-based implementation was trickier than I thought.

First you need to:

// cypress/integration/your-test.js
Cypress.on('window:before:load', (win) => {
  delete win.fetch
})

Then:

// pages/your-page.js
Entry.getInitialProps = async function() {
  window.fetch = require("unfetch").default
  ...
} 

Other combinations of delete & update code lines I tried didn't yield positive results. For example, when I had window.fetch = line in the test file it didn't work and fetch.toString() gave "native code". Not sure why, no time to explore further.

Axios solves the above but I don't like to bloat my bundle with extra stuff. You can inject XHR-based fetch for tests only.

4) The most important missing piece. You need to wait for route.

it("Has a correct title", () => {
  cy.visit("/")
  cy.server()
  cy.route("GET", "http://localhost:8080/api/documents/url/about", {title: "About+"}).as("about")
  cy.get("[href='/about']").click()
  cy.wait("@about") // !!!
  cy.get("h1").contains("About+")
})
Ivan Kleshnin
  • 1,667
  • 2
  • 21
  • 24
  • So, in this case, how did you stub the request/data-fetch on the server-side of Next.js? I only see client-side stubbing – Stralos Sep 20 '19 at 08:28
  • I guess the conclusion of the answer is "can't be done" - "test just HTML and couple tests to real data" – George Katsanos Mar 29 '21 at 18:53