mock/stub/ignore google recaptcha v3 requests on cypress tests

Viewed 831

we have many recaptcha v3 requests (like POST: https://www.google.com/recaptcha/api2/reload?k=XXXX) on the tested website.
That slows down the tests and make them less stable.
Recaptcha will be not verified on server on test environment, so we don't really need it (until production e2e test).
We wanted to stub the requests completely, but the client js code should receive something for actions to work.

right now we stub with global support/index.ts:

before(() => {
  cy.log('ignore google recaptcha');
  cy.intercept('POST', '**/*google.com/recaptcha/api2/**', { statusCode: 200, body: `["rresp","",null,null,null,""]` });
});

do you know alternative / bettter solution for this problem?

1 Answers

We have gotten this to work with existing FE tooling that calls into recaptcha APIs by using the following stub. This allows the FE code to stay unchanged but recaptcha to always report as success.

This does not defeat a properly configured recaptcha set up as the token (FAKE_TOKEN) will fail server side verification. It is only intended to be used when the BE is being mocked by doing a cy.intercept.

Please note that you might need to change the last line of this stub if the onload query param is passed any value other than ng2recaptchaloaded

/**
 * API Compatible Stub for Google Recaptcha V3.
 *
 * Always passes recaptcha checks locally - if this was used in real
 * life setting then the server side verification would fail.
 *
 */
const requestOptions = [];
window.grecaptcha = {
  ready: callback => callback(),
  execute: key => {
    if (requestOptions[key] && requestOptions[key].callback) {
      requestOptions[key].callback("FAKE_TOKEN");
    }
    return Promise.resolve("FAKE_TOKEN");
  },
  getResponse: key => {
    return 1;
  },
  render: (el, options) => {
    requestOptions.push(options);
    return requestOptions.length - 1;
  },
  reset: key => {}
};

// this should be based on the value passed to api.js?onload=<>
// but we hard code it for simplicity
ng2recaptchaloaded && ng2recaptchaloaded(window.grecaptcha);

Use it by by loading the js file as a buffer (by doing ,null) in cy.intercept

export function stubRecaptcha(cy: Cypress.cy) {
  cy.intercept(
    { url: /.*\/recaptcha\/api\.js.*/ },
    {
      fixture: "stub-recaptcha-api.js,null"
    }
  );
}

Also shared as this gist.

Related