Cypress: Update url without reloading AND have react-router respond

Created on 10 Jan 2019  路  4Comments  路  Source: cypress-io/cypress

Does anyone know how to update a route within a cypress test and have a react-router based app change state without refreshing the whole page?

I think because react-router manages its own history object, it doesn't listen to arbitrary URL changes. For example, using window.history.pushState(...) will update the URL without a refresh but the app itself doesn't respond

It seems like I'll need to get access to the history object used by react router within the cypress test itself.

Most helpful comment

Okay, I figured out a way to do this but it does require changing my app code:

import React, { Component } from "react";
import { Router } from "react-router-dom";
import AppContentManager from "./AppContentManager";
import { createBrowserHistory } from 'history';

const hist = createBrowserHistory();
if (window.Cypress) {
  window.tgHistory = hist
}

class App extends Component {
  render() {

    return (
      <Router history={hist}>
        <AppContentManager />
      </Router>
    );
  }
}

export default App;

And then for re-usability's sake I can just add a command to use this history everywhere:

/**
 * Goes to a route using react router and **without** reloading the page!
 * @memberOf Cypress.Chainable#
 * @name upload_file
 * @function
 * @param {String} selector - element to target
 */
Cypress.Commands.add("goToRoute", (route="") => {
  return cy.window().its('tgHistory').invoke('push', route)
});

All 4 comments

Okay, I figured out a way to do this but it does require changing my app code:

import React, { Component } from "react";
import { Router } from "react-router-dom";
import AppContentManager from "./AppContentManager";
import { createBrowserHistory } from 'history';

const hist = createBrowserHistory();
if (window.Cypress) {
  window.tgHistory = hist
}

class App extends Component {
  render() {

    return (
      <Router history={hist}>
        <AppContentManager />
      </Router>
    );
  }
}

export default App;

And then for re-usability's sake I can just add a command to use this history everywhere:

/**
 * Goes to a route using react router and **without** reloading the page!
 * @memberOf Cypress.Chainable#
 * @name upload_file
 * @function
 * @param {String} selector - element to target
 */
Cypress.Commands.add("goToRoute", (route="") => {
  return cy.window().its('tgHistory').invoke('push', route)
});

I'll close this but if someone knows how to do this without changing any app code I'd love to hear it. Thanks!

Thanks @tnrich, I think this is clean enough. We do the same thing with putting the redux store on window for Cypress, so we can dispatch actions and inspect the state (in the few cases where we need it).

Was this page helpful?
0 / 5 - 0 ratings