Exploring the Capabilities of Connected Container Functions through Jest and Enzyme Testing

I am currently working with a connected container that looks like this:

import React from 'react';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { autobind } from 'core-decorators';

const propTypes = {
  data: PropTypes.object,
  userData: PropTypes.object,
};

class ConnectedContainer extends React.Component {
    @autobind
    doSomethingImportant() {
      ...
    }

  render() {
    ....
  }
}

ConnectedContainer.propTypes = propTypes;

const mapStateToProps = state => ({ data, userData });
const mapDispatchToProps = (dispatch) => {
  return { actions: bindActionCreators(actions, dispatch) };
};
export default connect(mapStateToProps, mapDispatchToProps)(ConnectedContainer);

To test the doSomethingImportant method, I've written a test as follows:

import React from 'react';
import { shallow } from 'enzyme';
import ConnectedContainer from '.....'';
import configureStore from 'redux-mock-store';

const mockStore = configureStore();
const store = mockStore({ getState: () => null, dispatch: () => null, data: { data from fixture }, userData: { data from fixture } });
const container = (
  <ConnectedContainer
    store={store}
    actions={{}}
  />
);

describe('ConnectedContainer', () => {
  describe('doSomethingImportant', () => {
    it('returns something important', () => {
      const wrapper = shallow(container);
      expect(wrapper.instance().doSomethingImportant()).to.equal( ... some output here );
    });
  });
});

Despite my efforts, I keep encountering this error message:

TypeError: wrapper.instance(...). doSomethingImportant is not a function

I'm puzzled by why I can't seem to access the instance methods of my container. Can anyone shed light on what might be causing this issue?

Answer №1

Testing the Unwrapped Component

When testing your code, it is important to export the ConnectedContainer class itself, not the wrapped version. This way, you can focus on testing your actual code instead of the connect() function.

To achieve this, you can maintain the default export as the wrapped component and simply add the word export in front of the class definition:

export class ConnectedContainer extends React.Component { // Named export, for testing purposes only
    ...
}

In your test file, you can then import the ConnectedContainer with

import { ConnectedContainer } from '...'
and render it using shallow instead of the default export.

Naming Best Practices

It's worth noting that naming your component ConnectedContainer can be misleading. The component only becomes connected after being wrapped with the connect function. By exporting ConnectedContainer (as suggested), you are actually exporting a non-connected component class. Additionally, the term "container" may not accurately describe the component.

One common naming convention involves defining a constant that holds the return value of connect(), and naming it xxxContainer. For example:

export class IconView extends React.Component {  // Exported for testing
  // ... class implementation
}

function mapStateToProps(){...}
function mapDispatchToProps(){...}

const IconViewContainer = connect(mapStateToProps, mapDispatchToProps)(IconView);
export default IconViewContainer;  // Exported for use as a component in other views

Answer №2

Give this a shot:

const Component = (
  <ConnectedComponent
    store={store}
    actions={{}}
  />
);

Keep in mind, the key difference here is the uppercase C in ConnectedComponent. React typically recognizes classes and methods as components when their names begin with a capital letter. This could be causing your issue.

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

Confirm the email address using the autocomplete feature in the field

I'm currently utilizing Material UI to design an autocomplete field with multiple inputs that gives users the option to either choose from existing email addresses or input their own. An example of what I'm trying to achieve can be seen here: ht ...

Having trouble running `npm start` in React due to a `npm update check failed` error

When attempting to open a window to view my React app using npm start, I encounter the following error: npm update check failed │ │ Try running with sudo or get access │ │ ...

The process of integrating markdown markdown syntax into a React component using MDX

What is the most effective method to incorporate content from a markdown file foo.md into a component <Bar />? Will props need to be used for this? Can MDX handle such scenarios effectively? Your help is greatly appreciated! ...

Encountered an error at "emitErrorNT (node:internal/streams/destroy:151:8)" while attempting to develop a Next.js website

While working on my nextjs website, I encountered the following error: at emitErrorNT (node:internal/streams/destroy:151:8) at emitErrorCloseNT (node:internal/streams/destroy:116:3) at process.processTicksAndRejections (node:internal/proces ...

How should the main content be arranged with appbars and drawers in material-ui for optimal layout?

When working on React apps, I often rely on material-ui. Currently, for a project where I am utilizing the responsive drawer and appbar components, I am unsure about how to effectively position content around these navigation elements. Should I simply add ...

Tips for passing props to multiple child components in Vue?

In Vue, I'm curious about how to achieve the same functionality as declaring an object in React and passing it to multiple child components. const shared_props = { prop1: 'value1', prop2: 'value2', prop3: 'value3', ...

Unable to modify background color when Material UI Toggle Button is selected

I'm working on implementing the Material UI Toggle Button as a radio button to present 2 choices for a question to the user. Most aspects of it are functioning as expected, but I am facing an issue when trying to customize the style for the selected ...

What is the process for including a new item in an array of objects?

const data = [ { title: 'Tasks', items: ['complete assignments', 'study for exams'], }, { title: 'Ongoing', items: ['learn new skills', 'work on projects'], }, { titl ...

Getting the chosen option from a dropdown list mapped in ReactJS

I am working on a dropdown select option that is linked to the data of an array object called 'template_titles'. Currently, the value in the dropdown corresponds to the title in the object. My goal is to be able to extract and use the selected va ...

The localhost is not updating on subsequent runs of npm run dev after the initial run

Every time I launch npm run dev (for my nextjs application), it functions properly on the initial run. However, after making modifications to my files, saving them, and checking my localhost, the changes do not appear. What is the solution? Currently, I f ...

The API is not receiving the HttpOnly cookie

Currently utilizing next.js and strapi for my project. I'm facing an issue with setting an httpOnly cookie between my next.js front-end and my strapi app. Although the cookie is received by the backend, it's not present when I make a request to ...

When an Angular service is created, its properties are not immediately configured

My current task involves testing an Angular (4.1) service that looks like this: @Injectable() export class JobService { private answerSource = new Subject<AnswerWrapper>(); answer$ = this.answerSource.asObservable(); answer(answer: AnswerWra ...

Exploring Nextjs with server-side rendering and fetching data from

When utilizing the getServerSideProps function in Next.js to make a fetch request to my API, I encountered an issue where the origin header was coming back as undefined. This seems to be specific to requests made from the server in Next.js, as I am able ...

Using Material-UI in React, add a clear icon card component

Is there a way to place the clear icon on the top right side of the card, overlapping it? What is the best method to achieve this? https://i.stack.imgur.com/QbkXg.png For a live demo and code example, follow this link: CODESANDBOX <Paper sx={{ p ...

What are the different ways to customize the indicator color of React Material UI Tabs using hex

Just got my hands on this amazing Material UI component <Tabs textColor="primary" indicatorColor="primary" > <Tab label="All Issues"/> </Tabs> The documentation states that indicatorColor and textColor can only be set to ' ...

Exploring the functionality of closing Material UI Drawer on escape key in a React 16 app with RTL support

I am currently experimenting with the Material UI Drawer component. I expected it to close when pressing the Esc key or clicking outside of it, but unfortunately, it is not behaving as anticipated. I am utilizing the react testing library for my tests an ...

The information stored in the useRef hook experiences a delay when accessed through the useImperativeHandle function

After implementing useImperativeHandle from the Input Component to transfer ref data to the Login Component, I encountered an issue where the emailInputRef data was delayed compared to the inputRef data. const Login = () => { const router = useRouter( ...

Utilizing ObjectId for filtering and calculating overall cost in react.js: a guide

The table should only render once for Wade Ivan, with a total of 180 instead of 680. Seeking assistance to optimize my search class component. Currently, when searching for clients by their names based on ObjectId(clientdetails._id), the rendering returns ...

What is the best way to establish a state within a component?

How can I update the state of a component in ReactJS to show notifications again? import React, { useState } from 'react' const NotificationError = (props) => { const [notify, setNotify] = useState(false); console.log("notify.state: ...

Solidity smart contract failing to provide accurate output

Within my ERC20 solidity smart contract, I've implemented the following function: function getSummary() public view returns (string, string, address, uint, uint){ return( symbol, name, creator, balances[msg.sender], ...