How can i test a component with setProps() of enzyme - javascript

//in my component i have
{this.props.auth.isLoadding &&
<p className='text-info positionMessage'>Is registring...</p>
}
//in my test i have
it('should start a new component with set props', () => {
const props = {
auth: {
isAuth: false,
isLoadding: false
}
}
const wrapper = shallow(<ScreensCreateAccount {...props}/>)
wrapper.setProps({isLoadding: true})
//here is code for testing if <p>...</p> appeared. how can i do this?
})
my component starts with this.props.auth.isLoadding = false, and when a change it for true, the html too change, adding <p className='text-info positionMessage'>Is registring...</p>. How can i test it using shallow from enzyme?

Here is a working example that sticks to your code : https://codesandbox.io/s/r7owz8mykm
In your code you just forgot the auth level in your json for the prop isLoading.
{isLoadding: true}, instead of {auth: {isLoadding: true} }
But be aware that shallow rendering and enzyme may not be the right tool for testing your React component. I used it a bit but now I use react-testing-library : https://github.com/kentcdodds/react-testing-library and I am definitively happy with that. My tests are now more high level and interact with my components like a real user will do. I can refactor my component without breaking my tests, with enzyme it is, well, not so easy to write this kind of tests.
I really encourage you to at least read this and make your own opinion.
https://blog.kentcdodds.com/why-i-never-use-shallow-rendering-c08851a68bb7
If you already have some tests with enzyme no problem, you can use both libraries in the same project.

Related

How to test different types of test for a single render in React with testing-library?

I'm new in TDD for the React. I've decided to use the react-testing-library to start TDD for development. Suppose that, I should check a prop and simple text in component:
import { render, screen } from '#testing-library/react';
import Card from '../Card';
test('render without crash', () => {
render(<Card />);
expect(screen.getByText('Card Component')).toBeInTheDocument();
});
test('title', () => {
render(<Card title="test" />);
expect(screen.getByText('test')).toBeInTheDocument();
});
I used render two times two check different types of rendering for my component. But I was worry about performance... Is it best practice to separately use render in any tests? or I should create something like this common variable:
const Component = render(<Card title={...} prop2={} prop3={} ... />);
then use Component instead using render again?
I don't think this would be a bad practice. I usually use one of these approaches :
render my component once in a beforeEach, and use it in multiple test(), if I always need the same setup for each test (props, contexts, redux store...),
render my component in each test(), so I can adjust props and context and test multiple configurations.
See https://stackoverflow.com/a/61838982/2295549 for a more complete explanation, and some pros/cons.
But using render multiple times is not a bad practice, in fact it is a pattern used in official docs.

Correct way to unit test/mock shared export function using props from components - React

In my React project, I have a shared exported function:
//shared_functions.js
export function buildEndpoint(region, methodName) {
return (region in this.props.regionalEndpointsMap ? this.props.regionalEndpointsMap[region] : this.props.regionalEndpointsMap["default"]) + "/" + methodName;
}
that's used and imported in multiple components such as:
//SomeComponent.jsx
import { buildEndpoint } from 'src/util/shared_functions';
....
handleSubmit = async event => {
let response = await fetch(buildEndpoint(this.state.region, 'methodName'), {
....
The problem is I'm having trouble unit testing this function due to this.props.regionalEndpointsMap in the buildEndpoint function.
My question is what would be the correct way to unit test this function following best practices? Unit test it independently of any component that uses it? Test it from a component that uses it? Haven't been able to find a way to mock this.props.regionalEndpoints when trying to test the function independently, and when trying to test it from a component, the function is unrecognized:
//test.jsx
....
//props contains regionalEndpointsMap
wrapper = shallow(<SomeComponent {...props} />);
wrapper.instance().buildEndpoint('region', 'method')
//buildEndpoint is unrecognized
And as another question that may make the above a moot point, okay to try and access a property (props) in an exported function even though it's not guaranteed to have that property in a component it's used in? Or is it frowned upon? Would it be better to create a base component class with this function and make it the parent to the component classes that use it?
Sorry if these sound like dumb questions, new to React and unit testing with jest and enzyme.
To test the function independently you could mock it, something like this:
import { buildEndpoint } from 'src/util/shared_functions';
...
let result = ({
props : {regionalEndpointsMap : {default : 'd'} },
buildEndpoint : buildEndpoint
}).buildEndpoint("r", "m")
Personally though I would pass in regionalEndpointsMap to the function to avoid the need to access the this context.

Meteor React Subscription

What is alternative way of using package 'react-meteor-data' ? I'm using ES6 for writing react component. What would be best approach for writing meteor subscription in react component so that it will re-render the component if anything change on the server side.
What would be best approach for writing meteor subscription in react
component so that it will re-render the component if anything change
on the server side.
The best approach is using react-meteor-data. What is wrong with this package, that makes you think to not use it?
It even allows you to separate / decouple React Components from Meteor. This is really great because when you reach the point of having written some components that you want to reuse in another non-Meteor project you are free to go without greater hassle.
Of course you could write your own subscription container for react, but with this package you have all important stuff you need plus it is maintained and tested.
If you have trouble setting up a container for subscriptions, you may dig deeper into these tutorials:
https://guide.meteor.com/react.html
https://themeteorchef.com/tutorials/using-create-container
Using react-meteor-data, you first create a HOC container that subscribes to the data and passes it down as props to your component.
Container:
import { createContainer } from 'meteor/react-meteor-data';
export default FooContainer = createContainer(() => {
// Do all your reactive data access in this method.
// Note that this subscription will get cleaned up when your component is unmounted
var handle = Meteor.subscribe("todoList", this.props.id);
return {
currentUser: Meteor.user(),
listLoading: ! handle.ready(),
tasks: Tasks.find({listId: this.props.id}).fetch(),
};
}, Foo);
Component:
import FooContainer from './FooContainer';
class App extends React.Component {
render() {
return (
<div>
{this.props.currentUser.name}
</div>
)
}
}
export default FooContainer(App);
Check out React docs for Higher Order Components to understand how the container works.

What does #describe and #it methods do in TDD react testing?

I'm learning TDD with React from this site, but don't understand how the author got describe and it, aren't these usually from Jasmine? I don't see this package in the author's node_modules at his github nor does his tests.js import anything that looks like describe or it. Where are these two methods coming from?
import React from 'react';
import { expect } from 'chai';
import { shallow, mount, render } from 'enzyme';
describe('Test suite for User component', () => {
it('UserComponent should exist', () => {
let wrapper = shallow(<User />)
expect(wrapper).to.exist;
});
});
If that is the only it() statement that you are going to be using in your test suite, you do not really need the describe() block.
The describe() construct does indeed exist in Jest, it exists in Mocha as well.
The describe() function is used to group together certain sets of tests that have some common setup and tear down for each of them. This is why I said, based on the code you pasted, if you have nothing further to test, you do not need that describe() function.
So when you run create-react-app one of the libraries that got loaded automatically was the Jest test suite.
I would also rewrite that test, instead of UserComponent should exist, I would do
it('shows a user component', () => {
let wrapper = shallow(<User />);
expect(wrapper.find(User).length).toEqual(1);
});
So this is where I recommend to not just follow tutorials, but look up the documentation of the tools they are having you utilize in these tutorials. In the case of Enzyme, there is a really nice method called find() to find the component and it offers an array so you can add on .length and since its just one component of User you can add at the end .toEqual(1);

How can I test my react router?

I built a simple MyRouter component based on react-router. Now I'd like to test my routing logic, like this:
it('should show AboutPage for /about`, () => {
let vdom = renderMyRouterForPath('/about');
expect(vdom).toEqual(<AboutPage />);
}
I'm using plain Jasmine in Node, no Jest mocking magic. It would be also nice to avoid rendering the whole thing in DOM (virtual DOM should be enough, I don't mean to test DOM interactions).
I've had some success with setting history={ history.createMemoryHistory(path) } in Router, but this wasn't enough. I tried shallow rendering, but with no luck (it returns the Router build by MyRouter).
How can I implement the renderMyRouterForPath function?

Categories