How to test or get value from state in react? - reactjs

Hi could you please tell me How to test or get value from state in react ?
getting error
wrapper.instance(...).handleClickShowPassword is not a function
here is my code
https://codesandbox.io/s/l2lk4n794l
it("toggle showpassword value", () => {
wrapper.setState({ showPassword: false });
wrapper.instance().handleClickShowPassword();
expect(wrapper.state.showPassword).toEqual(true);
});

Since LoginContainer is an wrapped with an HOC, you either need to export the component without withStyles HOC or use dive on the wrapper to get the instance of the component. Also state is a function on component instance and hence you need to call it to access state
describe("<LoginContainer/>", () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<LoginContainer />);
});
it("toggle showpassword value", () => {
const comp = wrapper.dive();
comp.dive().setState({ showPassword: false });
comp.instance().handleClickShowPassword();
expect(comp.state("showPassword")).toEqual(true);
});
});
Working demo

Related

Why is JEST testing giving "Could not find "store" error when call setState?

I'm trying to test this:
(I need to confirm that when selectedDevice is called with DESKTOP prop, it calls openModal and that method sets the state of modalOpen to true)
openModal = () => {
this.setState({ modalOpen: true });
};
selectedDevice = () => {
const { device } = this.props;
const isMobile = device === MOBILE;
if (isMobile) {
this.closeWindow();
} else {
this.openModal();
}
};
and I'm testing like this (with JEST)
test('should openModal be called', () => {
const wrapper = mount(<Component
{...sampleProps}
deviceType={DESKTOP}
/>);
const selectedDevice = jest.spyOn(wrapper.instance(), 'selectedDevice');
selectedDevice();
expect(wrapper.state().modalActivated).toEqual(true);
});
Apparently, it seems to be reaching the openModal method in my component. However, I'm getting this error:
Invariant Violation: Could not find "store" in either the context or props of "Connect(Styled(Component))". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(Styled(Component))".
36 |
37 | openModal = () => {
> 38 | this.setState({ modalOpen: true });
| ^
I saw another solutions to that error message, but nothing seems to work for this specific error.
I already tried wrapping the component inside a Provider component with no luck.
You're getting the error because you're using a component which is wrapped inside of the connect HOC from react-redux and the connect HOC needs the redux Provider component with a state.
Your code should be something like this:
test("should openModal be called", () => {
const wrapper = mount(
<Provider store={CreateANewStoreForTest}>
<Component {...sampleProps} deviceType={DESKTOP} />
</Provider>
);
const selectedDevice = jest.spyOn(wrapper.instance(), "selectedDevice");
selectedDevice();
expect(wrapper.state().modalActivated).toEqual(true);
});
and for data on how to create a store read the DOC here

React-Jest Unit test an external module method that affects state

I am working on a React application using Jest.
I want to test an imported module component method (closemodal):
<Modal
visible={this.state.showModal}
closemodal={() => this.setState({ showModal: false })} // <= this one
type="slideInDown"
>
I tried in my unit test to spy Modal closemodal method like that:
import Modal from "react-animated-modal";
let spyOnCloseModal;
beforeEach(() => {
spyOnCloseModal = jest.spyOn(Modal, "closemodal");
wrapper = shallow(<App />);
});
But when UT running I get this error:
Cannot spy the closemodal property because it is not a function; undefined given instead
Try passing a mock function.
test("checks closemodel", () => {
const props = {
closemodal: jest.fn()
};
const wrapper = shallow(<Modal {...props} />);
// trigger your `closemodal` function here
expect(props.closemodal).toHaveBeenCalledTimes(1);
});

Jest: How to test prop that is an anonymous function?

I have a component that loads another component, sending it an anonymous function as a prop:
export class Header extends Component {
constructor(props) {
super(props)
this.state = { activeTab: TAB_NAMES.NEEDS_REVIEW }
}
filterByNeedsReview() {
const { filterByNeedsReviewFn } = this.props
this.setState({ activeTab: TAB_NAMES.NEEDS_REVIEW })
filterByNeedsReviewFn()
}
...
render() {
return (
<Container>
...
...
<FilterTab
active={this.state.activeTab === TAB_NAMES.NEEDS_REVIEW}
name={TAB_NAMES.NEEDS_REVIEW}
count={40}
onClick={() => this.filterByNeedsReview()}
/>
...
...
</Container>
)
}
}
I have this failing test:
it('renders a filter tab with the right props for needs review', () => {
const filterByNeedsReviewFn = jest.fn()
expect(
shallowRender({ filterByNeedsReviewFn })
.find(FilterTab)
.findWhere(node =>
_.isMatch(node.props(), {
active: true,
name: 'Needs Review',
count: 40,
onClick: filterByNeedsReviewFn, //<-------------- THIS DOESN'T WORK
})
)
).toHaveLength(1)
})
How would I test that onClick is the right thing?
I believe you don't need to check how internal event handlers look like. You might be interested in different things: if triggering event handler changes component as you expect(.toMatchSnapshot() is much better here instead of testing structure manually with .toHaveLength) and if callback you've passed through props is called when it should to(.toHaveBeenCalled). What if component is changed some day not to just call .props.filterByNeedsReviewFn() but also do some stuff like calling anything else? should your test fail just because there is named method passed somewhere inside? I believe it is not.
So I see your test to be
it('renders a filter tab with expected props after clicking', () => {
const comp = shallowRender({});
comp.find(FilterTab).simulate('click');
expect(comp).toMatchSnapshot();
});
it('calls callback passed after clicking on filter tab', () => {
const filterByNeedsReviewFn = jest.fn()
const comp = shallowRender({ filterByNeedsReviewFn });
comp.find(FilterTab).simulate('click');
// let's ensure callback has been called without any unexpected arguments
expect(filterByNeedsReviewFn ).toHaveBeenCalledWith();
});
I don't think you actually needed this code but I wanted to illustrate how clear such approach could be. Your component have API: props callback it calls and render output. So we can skip testing internals without any pitfalls

When to use "Component.WrappedComponent" when writing enzyme tests

What I'm trying to do:
I'm trying to use shallow rendering from enzyme by following the below pattern which works for many other components in my project.
describe('>> MyComponent - Render', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<MyComponent.WrappedComponent
actions={{}}
history={}
/>);
});
it("test something", () => { expect(wrapper).toEqual(1); });
});
What's the problem I have:
I got an error saying "Cannot read property 'contextTypes' of undefined", which means wrapper is undefined. But when I change <MyComponent.WrappedComponent /> to just <MyComponent />, the tests are successful. This is my code:
describe('>> Legends - render', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<Legends textsAndColor={[]} />);
});
it('+++ render the component', () => {
expect(wrapper.length).toEqual(1);
});
it('+++ match snapshot', () => {
expect(wrapper).toMatchSnapshot();
});
});
Question I have:
What exactly does .WrappedComponent do ? And why does <MyComponent /> works but not <MyComponent.WrappedComponent /> ?
By using .WrappedComponent you are getting access to component, wrapped by redux's connect function.
I assume that most of your components are connected (since there are no problems with use of .WrappedComponent) and component that throwing described error isn't connected.
I suggest you to read redux docs to find out how to write tests for this case. Briefly said they suggest to have default export for your connected component and non-default for raw component. And then import only raw component for testing purposes, like this:
import { MyComponent } from './path/to/my/component`;
after this you will be able to mount (or shallow) your raw component like this:
describe('>> MyComponent - Render', () => {
let wrapper;
beforeEach(() => {
wrapper = shallow(<MyComponent />);
}
});

Set URL params while testing with Jest & Enzyme

My component has:
class Search extends Component {
constructor(props) {
super(props);
this.state = {
searchTerm:
typeof this.props.match.params.searchTerm !== "undefined"
? this.props.match.params.searchTerm
: ""
};
}
and the test is:
test("Search should render correct amount of shows", () => {
const component = shallow(<Search shows={preload.shows} />);
expect(component.find(ShowCard).length).toEqual(preload.shows.length);
});
I get
TypeError: Cannot read property 'params' of undefined
How can I fix that or how to set query params in my test?
It seems like when outside the test, the Search component receives the match props correctly.
You could pass it as props when shallow rendering it in the test:
test("Search should render correct amount of shows", () => {
const match = { params: { searchTerm: 'foo' } }
const component = shallow(<Search shows={preload.shows} match={match}/>);
expect(component.find(ShowCard).length).toEqual(preload.shows.length);
});
And in that case, you're not changing the component under test in a bad way, your test case just found a bug, which is good and should be aimed in tests, and you improved the component by implementing a default props, making it more robust.
you should defined a location first in your it/test.
it('App init', async () => {
const location = {
...window.location,
search: '?scope=3&elementId=25924',
};
Object.defineProperty(window, 'location', {
writable: true,
value: location,
})
……
})
I also faced same issue and solved by adding a match prop in the component when you pass it in shallow or mount method. Here is the code:
test("Add param in component", () => {
const match = {params : { id: 1 } };
const component = shallow(<YourComponent match={match} />);
expect(/*Write your code here */);
});
As you can see I and having a param as id, replace with whatever is your's.

Resources