1

I am currently using testcafe for my e2e tests.

As testcafe doesn't support async code, I have to mock my graphql queries.

Is there any other way than using RequestMock function ?

It's not really developer friendly as it's heavily REST focused

EDIT:

Regarding the fact that I testcafe doesn't allow the usage of async code, here is some details: The setBody function is lost if I try to use async code (query real data). There is an issue here

const handler = async (req, res) => {


 // ok
  res.setBody('foobar')
  data = await Promise.resolve({ some: 'data' })
  // setBody is no longer defined
  res.setBody(JSON.stringify(data))
}
fixture('Register')
.page('http://foobar/register')
.requestHook(handler)

EDIT 2:

I have added the two files I am currently using.

Please take a look at apolloHook.js just before the export default

// apolloHook.js
import { RequestMock } from 'testcafe'
import fetch from 'node-fetch'
import gql from 'graphql-tag'
import configureApolloClient from '../../../src/ApolloClient'
const urlToCatch = 'http://127.0.0.1/index.php/graphql/'
const client = configureApolloClient({
  uri: 'http://nginx/index_test.php/graphql/',
  fetch
})
const handler = async (req, res) => {
  const body = JSON.parse(req.body.toString('utf8'))
  const query = gql`${body.query}`
  const { variables } = body
  let data = null
  if (body.query.startsWith('query')) {
    data = await client.query({ query, variables })
  } else {
    data = await client.mutate({ mutation: query, variables })
  }

  // res.setBody is undefined !

  res.setBody(JSON.stringify(data))
}
export default RequestMock()
  .onRequestTo({ url: urlToCatch, method: 'POST' })
  .respond(handler)
// register.js
import { Selector } from 'testcafe'
import { REGISTER_FIXTURES } from '../fixtures'
import { testInput, testPhoneInput, testCountryInput, testCountriesInput, testSelect } from '../utils/utils'
import apolloHook from '../utils/apolloHook'
const registerUrl = 'http://front:3000'
//Uncomment for local testing
//const registerUrl = 'http://127.0.0.1:3000'
fixture('Register')
  .page(registerUrl)
  .requestHooks(apolloHook)
test('Fill out sign up', async t => {
  await testInput(t, Selector('[data-testid=\'email\']'), 'john.doe@professional.com')
  await t
    .click(Selector('[data-testid=\'send-me-a-code\']'))
    .expect(Selector('[data-testid=\'one-time-password-button\']').innerText).eql('Submit')
})
  • 1
    TestCafe has async code in some of their examples? What makes you think it doesn't support async? https://devexpress.github.io/testcafe/documentation/test-api/built-in-waiting-mechanisms.html – Inch High Jan 21 '20 at 16:42
  • as seen here: https://github.com/DevExpress/testcafe/issues/4467#issuecomment-554927423 The setBody function is lost after awaiting any promise – Bamboozilla Jan 21 '20 at 16:51
  • 2
    Could you please describe the issue in greater detail? Please provide full code of your attempts to write a test. Also, note that you cannot pass your `handler` as an argument of the `requestHook` method. The syntactically correct usage is the following: `var mock = RequestMock().onRequestTo('http://external-service.com/api/').respond(handler)` – Alex Kamaev Jan 22 '20 at 11:31
  • @AlexKamaev I have added the code – Bamboozilla Jan 23 '20 at 13:04
  • 1
    I see, you mean TestCafe does not allow to make the `response` method asynchronous. At this moment, I do not see any workaround for this. Please add comments or votes to the github issue you reported to show the TestCafe team that the issue is a priority. – Alex Kamaev Jan 24 '20 at 10:48

1 Answers1

0

I am pretty sure, you got the solution now as testcafe natively supports async/await inside respond hook.

you can also try testcafe-graphql-mock library to mock your graphql queries in runtime using RequestMock and some custom methods provided by the library.

Add this library as a dev-dependency

npm i -D testcafe-graphql-mock

Now, you can use the custom commands:

import { mockGraphQL } from 'testcafe-graphql-mock';
 
// define the schema
const schema = `
type Person {
  firstname: String!
  surname: String!
}
 
type Query {
  people: [Person]
}
`;
 
// define the mock
const mock = {
  Query: () => ({
    people: () => [
      {
        firstname: 'Lee',
        surname: 'Byron',
      },
    ],
  }),
};
 
// create traditional testcafe request mock
const requestMock = RequestMock()
  .onRequestTo({ url: 'http://localhost:3000/graphql', method: 'POST' })
  .respond(async (req, res) => {
    await mockGraphQL(
      {
        schema,
        mock,
      },
      req,
      res
    );
  });
 
// now call the testcafe request mock in fixures as request hooks
fixture(`GraphQL Mock test`)
  .page('http://localhost:3000/')
  .requestHooks(requestMock);
 
test('test graphql mock data', async (t) => {
  await t.click(Selector('button'));
  await expect(Selector('div')).contains('Lee Byron');
});

You can also add delay to the response:

await mockGraphQL(
      {
        schema,
        mock,
        delay: 5000,
      },
      req,
      res
    );
Dharman
  • 30,962
  • 25
  • 85
  • 135
Abhinaba
  • 376
  • 1
  • 8