What is the best way to retrieve app.state in a Remix project when running a Cypress test?

One way Cypress can expose an app's state to the test runner is by using the following approach in React:

class MyComponent extends React.Component {
  constructor (props) {
    super(props)
    // only expose the app during E2E tests
    if (window.Cypress) {
      window.app = this
    }
  }
  ...
}

Subsequently, you could retrieve your state in a test with

cy.window()
  .its('app.state')
  .should('deep.equal', myStateObject)

However, the challenge arises when working with Remix projects that primarily rely on functional components. I attempted to implement this functionality in my root.tsx component utilizing a useEffect call:

export default function App() {
    useEffect(() => {
        window.app = App;
    }, []}
}

I also experimented with incorporating the logic in the root route (routes/index.tsx) by importing the <App /> component and applying it within the useEffect function without success. With no clear solutions found in Remix's GitHub issues, I am at a loss for what to do next. Any guidance would be greatly appreciated! Thank you!

Answer №1

I haven't had much experience working with Remix, but I came across a helpful question that might be of use:
React - retrieving a component from a DOM element for debugging.

Paying attention to the final paragraph is crucial.

Function components
Unlike classes, function components do not have traditional "instances", which means you cannot simply tweak the FindReact function to return an object with forceUpdate, setState, etc. for function components.

However, you can still access the React-fiber node for that element, containing its props and state. To achieve this, adjust the last line of the FindReact function as follows: just return compFiber;

There's a library called cypress-react-app-actions that provides this functionality for Cypress

export const getReactFiber = (el) => {
  const key = Object.keys(el).find((key) => {
    return (
      key.startsWith('__reactFiber$') || // react 17+
      key.startsWith('__reactInternalInstance$') // react <17
    )
  })
  if (!key) {
    return
  }
  return el[key]
}

// react 16+
export const getComponent = (fiber) => {
  let parentFiber = fiber.return
  while (typeof parentFiber.type == 'string') {
    parentFiber = parentFiber.return
  }
  return parentFiber
}

One of the sample tests includes:

/// <reference types="cypress" />

import { getReactFiber, getComponent } from '../support/utils'

it('calls Example double()', () => {
  cy.visit('/')
  cy.get('.Example').within(() => {         // select via className of component 
    cy.contains('[data-cy=count]', '0')
    cy.get('[data-cy=add]').click().click()
    cy.contains('[data-cy=count]', '2')
    cy.root().then((el$) => {
      const fiber = getReactFiber(el$[0])
      console.log(fiber)
      const component = getComponent(fiber)
      console.log(component.stateNode)
      cy.log('calling **double()**')
      component.stateNode.double()       // work with component for functional
    })
    cy.contains('[data-cy=count]', '4')
  })
})

This test example pertains to class components, but with the insights provided in the Function components section above, you would utilize the component object instead of component.stateNode.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

"Interact with jQuery by sliding side to side or in a circular motion

I am in need of assistance with sliding images using jQuery back and forth, or making them go round in a loop. Currently, the images slide up to the last element and then swiftly return to the first div, which is not visually appealing at all. I understa ...

Ways to remove the address bar from a mobile browser like Chrome or an Android browser

Is there a way to make videojs go full screen on Android devices when the URL is entered, without displaying the address bar? ...

Revealed the previously hidden private variables within the Revealing Module Pattern

I have encountered an issue while implementing the Revealing Module Pattern, as I am struggling to expose a modified private property. var myRevealingModule = (function(){ var name = 'Samantha'; function updateName () { name = ...

The integration of Raphaeljs library with SmartPhones opens up a world of

I recently incorporated the incredible JavaScript library, RaphaelJS, into my website to create maps, animations, and interactive features. Interestingly, I have observed that the scripts utilizing this library function seamlessly on iPhones but encounter ...

Trouble encountered with bootstrap toggling when multiple identical inputs are used

Problem with Bootstrap toggle not working on multiple identical inputs unless the first input is pressed. Even then, not all inputs are checked/unchecked. I've created a small example I want to ensure that when one input is toggled, all others have ...

Error message: validator is not defined when integrating jquery.validate with jquery.uploadfile package

Currently, I am facing an issue while attempting to incorporate both jquery.validate and jquery.uploadfile on the same page. The error message I'm receiving is: TypeError: validator is undefined if ( validator.settings.rules ) { Interestingly, if ...

Why does my POST request result in [object Object] being returned?

I am just starting to learn AngularJS and I am unsure if my POST request is functioning correctly. After making the request, I am receiving an [object Object] response. What does this error indicate? Could it be related to an issue with the form? //Acti ...

Utilizing Angular Pipes for Utilizing Location

The Location service in Angular is described as "A service that applications can use to interact with a browser's URL." One of its methods, getState(), provides "the current state of the location history," while another method, subscribe(), allows us ...

Tips for showcasing all values in a nested array

In my Vue application, I am dealing with a nested array where users can select one date and multiple times which are saved as one object. The challenge I am facing now is how to display the selected date as a header (which works fine) and then list all the ...

Eliminating redundant JSON records upon fetching fresh data

I have a list containing duplicate entries: var myList = [ { "id": 1, name:"John Doe", age:30 }, { "id": 2, name:"Jane Smith", age:25 }, { "id": 3, name:"John Doe", age:30 }, { &qu ...

Enter key triggering input change event is unresponsive in Internet Explorer

$("#inputBoxWidth").change(function() { var curValue = $("#inputBoxWidth").val(); alert(curValue); }); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <form> <input type="text" id="inputBo ...

What could be causing the state object in React to not be updating correctly? There seems to be a discrepancy between the expanded and

Displayed on the console is a screenshot showing <br><br> I am working with React.js, and the object displayed in the image is an element within an array that is part of the state object. I'm puzzled by what's happening. The object a ...

Clear v-model without changing its associated values

I'm facing an issue with my <input> fields, which look like this: <input type="text" v-model=user.name" /> <input type="text" v-model="user.phone" /> <button @click="add">add user</button> Whenever the add user button i ...

trigger a p:ajax event by employing a right-click action

Currently, I am utilizing JSF and Primefaces 5.2. A peculiar observation I made is that when a commandLink is used with the onclick event and p:ajax, it creates a selection effect. <h:commandLink id="commandLink"> <p:ajax event="click"/> </ ...

Expanding the Warnings of React.Component

When I create a new class by extending React.Component in the following manner: export default class App extends React.Component<any, any > { constructor (props: React.ReactPropTypes) { super(props); } // other code } I encountere ...

Navigating URL to switch data access

Is there a way to toggle the visibility of a div when I add #ID at the end of the URL? For instance, if I access a URL like domain.com/xxxxxx#01, then the specified div should be displayed. $(document).ready(function() { $(".toogle_button_<?php echo ...

How can I force an element to overflow without being affected by its parent's overflow style in CSS/HTML/JS, even if the parent is

I've come across many inquiries on this subject, but the proposed solutions never seem to work when dealing with ancestors that have absolute positioning. Take this example: <div id='page'> <div id='container' style= ...

What is the proper way to update data in reactjs?

I previously had code that successfully updated interval data in the browser and locale without any issues. class Main extends Component { constructor(props) { super(props); this.state = {data: []} } componentWillMount() { fetch('fi ...

Having trouble getting Ajax post to function properly when using Contenteditable

After successfully implementing a <textarea> that can post content to the database without needing a button or page refresh, I decided to switch to an editable <div> for design reasons. I added the attribute contenteditable="true", but encounte ...

Tips for initiating a function at a designated scroll point on a webpage

Currently, I am testing out a code snippet that allows images to flip through in a canvas element. I'm curious if it's possible to delay the image flipping effect until the viewer scrolls down to a specific section of the page where the canvas i ...