7

I'm building a single page web application (SPA) with server side rendering (SSR).

We have a node backend API which is called both from the node server during SSR and from the browser after initial rendering.

I want to write e2e tests that configures API responses (like with nock) and work both with browser calls and SSR server calls. some pseudo-code :

it('loads some page (SSR mode)', () => {
  mockAPI.response('/some-path', {text: "some text"}); // here i configure the mock server response
  browser.load('/some-other-page'); // hit server for SSR response
  expect(myPage).toContain('some text');
})   

it('loads some other page (SPA mode)', () => {
  mockAPI.response('/some-path', {text: "some other text"}); // here i configure another response for the same call
  browser.click('#some-link'); // loads another page client side only : no SSR here
  expect(myPage).toContain('some other text');
})   

Currently Cypress allows me to mock fetch on the browser but not on the server.

Is there anything to achieve that ? Preferably with node libs.

sylvain
  • 1,781
  • 2
  • 17
  • 33

2 Answers2

5

MockTTP can do that. Excerpt from the doc :

const superagent = require("superagent");
const mockServer = require("mockttp").getLocal();

describe("Mockttp", () => {
    // Start your server
    beforeEach(() => mockServer.start(8080));
    afterEach(() => mockServer.stop());

    it("lets you mock requests, and assert on the results", () =>
        // Mock your endpoints
        mockServer.get("/mocked-path").thenReply(200, "A mocked response")
        .then(() => {
            // Make a request
            return superagent.get("http://localhost:8080/mocked-path");
        }).then(() => {
            // Assert on the results
            expect(response.text).to.equal("A mocked response");
        });
    );
});
sylvain
  • 1,781
  • 2
  • 17
  • 33
  • 1
    Here's an example repo to showcase Cypress + Mockttp integration: https://github.com/mvasin/cypress-mockttp – Mikhail Vasin May 11 '20 at 16:55
  • Is it able to mock local API routes? Since they run on the same port as your Next app? – Eric Burel Oct 01 '20 at 12:00
  • I'm getting "Network request failed Because this error occurred during a before each hook we are skipping all of the remaining tests." and I followed the examples to the letter. – George Katsanos Mar 29 '21 at 18:51
3

We used a particularly ugly solution, that breaks the speed of cypress, but we needed that in order to mock/fake socket calls.

You can make a real simple express server that starts before running your tests. This 'real fake server' will be able to respond what you need. Here are the specs of our:

  • POST on / with method, path and {data} in body params in order to setup a route
  • GET/POST/PUT/DELETE on /path responds {data}
  • DELETE on / clear all the routes

Let's consider your 'real fake server' run on 0.0.0.0:3000; you'll do:

beforeEach() {
   cy.request('DELETE', 'http://0.0.0.0:3000/');
}

it('loads some page (SSR mode)', () => {
  cy.request('POST', 'http://0.0.0.0:3000/', {
    method: 'GET',
    path: '/some-path', 
    data: {text: "some other text"}
  }) // here i tell my 'real fake server' to 
     // respond {text: "some other text"} when it receives GET request on /some-path
  browser.load('/some-other-page'); // hit server for SSR response
  expect(myPage).toContain('some text');
})   

it('loads some other page (SPA mode)', () => {
  cy.request('POST', 'http://0.0.0.0:3000/', {
    method: 'GET',
    path: '/some-path', 
    data: {text: "some other text"}
  }); // here i configure another response for the same call
  browser.click('#some-link'); // loads another page client side only : no SSR here
  expect(myPage).toContain('some other text');
}) 

Important : the resquests need to be in localhost. You won't be able to stub something external. (Hence, make an env var in order to request localhost:xxxx instead of google.com when you test your app)

You won't be able to control the 'real fake server' otherwise than this cy.request because your tests scripts run in the browser (correct me if I'm wrong) and the browser can't run an express server.

Linaco
  • 41
  • 3
  • This is what we finally did. I was looking for an existing mock server (in node preferably). I finally found one : have a look at my answer – sylvain Jul 20 '18 at 09:57