Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I access React component's local state using Cypress?

I'm using react with redux and testing with cypress, I was able to access the store using cy.window().its('store').invoke('getState').then((state) => {} But how do i access a component's local state rather than the application store?

I tried

cy.get('.simple-component').its('getState')

or

cy.get('.simple-component').invoke('getState')

but Cypress is returning "CypressError: Timed out retrying: cy.invoke() errored because the property: 'getState' does not exist on your subject" And on the Cypress console (in chrome) it's yeilding:

Yielded:   
<div class="simple-component" getstate="[object Object]"></div>

It seems that's caused by React removing the methods from the DOM so i need to access it in React rather than in the DOM?

import React, { Component } from 'react';

class simpleComponent extends Component {
    constructor(props) {
        super(props)
        this.state = {
            sample: "hello"
            }
    }
    // getState() just for testing on cypress
    getState() {
      return this.state
    }
    render(){
      return <div className="simple-component" getState={this.getState()}></div>
    }    
}

As an alternative can i export the local component state at the end of the simple-component using window.store?

like image 483
Omar Avatar asked Jan 27 '23 13:01

Omar


1 Answers

>= version 7.0.0

As of Cypress 7.0, the new Component Test Runner is now bundled with Cypress

From https://www.cypress.io/blog/2021/04/06/cypress-component-testing-react:

We still need to install the react adapter to mount components:

yarn add -D cypress @cypress/react @cypress/webpack-dev-server

add a glob pattern matching your component tests to cypress.json:

{
  "component": {
    "testFiles": "**/*.test.{js,ts,jsx,tsx}",
    "componentFolder": "src"
  }
}

Tell Cypress to use @cypress/webpack-dev-server for component tests. in cypress/plugins/index.js:

const injectDevServer = require("@cypress/react/plugins/react-scripts")

module.exports = (on, config) => {
  injectDevServer(on, config)
  return config
}

This will configure the Cypress Webpack Dev Server to use the same Webpack configuration as Create React App uses.

If you are using a different template, like Next.js, we have some other adapters available. It's also possible to create your own adapter.

< version 7.0.0

There's a Cypress Plugin for that, called react-unit-test. It gives you the ability to mount React components directly (adds a cy.mount() command) and provides access to the component's internal state.

Here's an example from the repo's readme:

// load Cypress TypeScript definitions for IntelliSense
/// <reference types="cypress" />
// import the component you want to test
import { HelloState } from '../../src/hello-x.jsx'
import React from 'react'
describe('HelloState component', () => {
  it('works', () => {
    // mount the component under test
    cy.mount(<HelloState />)
    // start testing!
    cy.contains('Hello Spider-man!')
    // mounted component can be selected via its name, function, or JSX
    // e.g. '@HelloState', HelloState, or <HelloState />
    cy.get(HelloState)
      .invoke('setState', { name: 'React' })
    cy.get(HelloState)
      .its('state')
      .should('deep.equal', { name: 'React' })
    // check if GUI has rerendered
    cy.contains('Hello React!')
  })
})
like image 88
bkucera Avatar answered Mar 06 '23 17:03

bkucera