How to overwrite HTML with Cypress

Here's a quick snippet to allow you change the HTML of a page before Cypress fires your tests.

In an ideal world you would want to have different server side rendered HTML pages and you would just call page-1.html and page-2.html but in my case the component I'm trying to test inherits a configuration from a central location. It is simply not possible for me to amend that central configuration, as it would affect all other tests/components.

Thus we make use of the onBeforeLoad callback function to change the HTML in Cypress. The callback function is described as:

Called before your page has loaded all of its resources.

In the example below I'm query selecting the h1 element and changing its content before Cypress fires the tests. This also works very nicely in case you want to change any data attributes or DOM elements before your custom JavaScript (the one in the test page, not in Cypress) fires:

describe('My component', () => {
  before(() => {
    cy.visit('index.html', {
      onBeforeLoad() {
        cy.document().then((doc) => {
          const $heading = doc.querySelector('h1');

          $heading.textContent = 'New H1';

  it('Component is visible', () => {
      .contains('New H1');
});Code language: JavaScript (javascript)

Documentation for visit()


So, it turns out this cy.document().then() does a race condition somewhere. I could run my tests like 5 times and at least one would not produce the desired effect ❌ Surely the HTML when I inspected was updated but it was not updated before my page's JavaScript fired πŸ₯²

I couldn't find a way to prevent this race condition. Even if the documentation says the cy commands are not promises (yes, they do mention the use of then but according to them it's not a promise).

I just had to rethink my page's JavaScript and use the window object, which seems to be very reliable, and not modify the HTML. I know this might not work for your use case, you arrived at this post looking to update the HTML before visiting a page. Sorry about that! πŸ™‡β€β™‚οΈ

In any case, here's the snippet (just like the official docs):

cy.visit('index.html', {
  onBeforeLoad: (contentWindow) => {
    // contentWindow is the remote page's window object
    contentWindow.myObject = '1234';
})Code language: JavaScript (javascript)

Leave a Reply

Your email address will not be published. Required fields are marked *