For the life of me I can't figure out how to simulate a click event on a child component.
class Parent extends Component {
childClicked() {
console.log('hello')
}
render() {
return (
<div>
<Child onClick={() => this.childClicked()} />
</div>
)
}
}
In my test I am saying:
const spy = sinon.spy(Parent.prototype, 'childClicked')
const wrapper = mount(<Parent />)
wrapper.find('Child').simulate('click')
console.log(spy.called)
The childClicked method is still showing as not clicked. If I change the Child component to a simple button, the spy shows that the childClicked method was called.
I looked through a bunch of Github issues and have not seen this problem anywhere else.
_Is there something I am doing wrong?_
Try it with shallow instead of mount.
@ljharb The problem with shallow is my component is nested about 3 levels deep. I kept it at one level in the example for simplicity sake.
My recommendation would be to shallow-render every level.
On using mount() I'm able to simulate the click, but am unable to detect the function call of the parent component which was sent as props to the child. With shallow render, wrapper.find('.btn').first().simulate('click') doesn't work as it does on mount.
umm was there a solution ? any way of simulating on click of a child component
@jsj14 You can shallow render every level. I just assumed that the solution would be more elegant than that though.
I'm having this issue with Enzyme 3+. Will it be fixed ?
Same here, simulating click on direct child-components calls functions as expected, but simulating click on components nested deeper in the components tree does not call the functions (does not raise any error either).
^ experiencing this as well
It's a pretty common use case - no solution till now?
@protoEvangelion, I am Expriencing the same here. shallow is not a good enough solution since I need to to through the whole component lifecycle. please reopen this issue.
Hi @protoEvangelion , i am facing the same problem. Any solution u got ?
Hi everyone, i use wrapper.find('div.label.barButton').get(0) to get below:-
{ '$$typeof': Symbol(react.element),
type: 'div',
key: null,
ref: null,
props:
{ className: 'label barButton',
onClick: [Function],
children: 'HOME_CHATS_SEND' },
_owner: null,
_store: {} }
i want to perform a click event here. so i did wrapper.find('div.label.barButton').get(0).simulate('click');
but getting error - TypeError: wrapper.find(...).get(...).simulate is not a function
someone please tell me how to do this click event. please help
@PriyalSayonetech could you try
wrapper.find('div.label.barButton').at(0).simulate('click')
(at(0) is important here)
?
thankyou for your response @moniikag ,i tried as you mentioned above. but still result is negative.
i have a div like this in react-
<div className="label barButton" onClick={this.handleEventSendMessage}>
{Texts.get(this.props.sendOptions.labelKey)}</div>
onClick in above is readonly, so i cannot pass anything to it.
when i console wrapper.find('div.label.barButton').get(0) , the output is as below.
{ '$$typeof': Symbol(react.element),
type: 'div',
key: null,
ref: null,
props:
{ className: 'label barButton',
onClick: [Function],
children: 'HOME_CHATS_SEND' },
_owner: null,
_store: {} }
and when console wrapper.find('div.label.barButton').get(0).props.onClick, the output is this:-
function (_) {
if (_this.props.file) {
sendFunction(_this.props.file);
_this.props.uploadFile(null);
} else {
_this.sendTextMessage(sendFunction);
}
}
But i cannot perform simulate('click') action here. Please help
@PriyalSayonetech again, you can't use get if you want to use "simulate" - simulate is an enzyme method, and get unwraps the enzyme wrapper. Only use at, not get.
Thanks @ljharb @moniikag .issue was- i was using both get and at, which didn't work out well
Hi guys, I'm here with another issue.
Its reactjs. my
<div class="conversationItem"><span>piloy</span>.....</div><div class="conversationItem active"><span>piloy</span>.....</div>
This is the test i wrote to simulate the click activity:-
wrapper.find('div.conversationItem').simulate('click');
wrapper.update();
expect(wrapper.find('div.conversationItem.active')).to.have.length(1);
But its not working as i expected.
div.conversationItem.active is never found. it's count is 0.
@ljharb @moniikag @protoEvangelion @jsj14 @ulfryk , People, Please help me to overcome this.
@mrbinky3000 .prop('onClick')()
expect(wrapper.find('name of the parent class').closest('.conversationItem active')).to.have.length(1)
Tried this 鈽濓笍 ? @PriyalSayonetech
Also try keeping classnames as .conversationItem-active
@jsj14 I tried
expect(wrapper.find('name of the parent class').closest('.conversationItem active')).to.have.length(1)
in a similar situation and it didn't actually click the button to change the class. Here's my code.
it('cleanStatus is updated to hotelRoomDirty from hotelRoomClean', () => {
const wrapper = mount(<Keeper />);
wrapper.find(button).at(1).simulate('click');
wrapper.update();
expect(wrapper.find('.hotelRoomClean').length).toBe(7);
});
cleanStatus(e) {
if (e.target.className === "hotelRoomClean") {
e.target.classList.add("hotelRoomDirty");
e.target.classList.remove("hotelRoomClean");
} else {
e.target.classList.add("hotelRoomClean") ;
e.target.classList.remove("hotelRoomDirty") ;
}
}
<button type="button" className="hotelRoomClean" onClick= {this.cleanStatus} id="button">101</button>
Any other suggestions?
I figured out that you can string together .find() to access nested components:
```
it("'send message' button responds to click event", () => {
const mockCallBack = jest.fn();
const wrapper = mount(
);
wrapper.find("Helpform").find("button").simulate("click");
expect(mockCallBack.calledOnce).toBe.true; >>>passes
});
This works if there is just one button to find.
.at(0) or .first() seems to work for picking one button to click one out of many in the same component. If there were three buttons in the wrapper component above, clicking the third would be
wrapper.find("Helpform").find("button").at(2).simulate("click");
```
Try this:
2 nested level.
const spy = sinon.spy
const GrandParent = mount(<GrandParent childClicked={spy}/>/>)
const Parent = mount(<Parent childClicked={GrandParent.props().childClicked}/> />)
Parent.find('Child').simulate('click')
console.log(spy.called)
Not 100% sure I was having a problem for the same reasons as those above, but a "gotcha" I ran into vis-脿-vis this issue: once you simulate the click, you have to look _in the mounted component_ (not in any filtered subcomponent) to see the changes. This is what was tripping me up (sending me searching and finding this issue), so I'm leaving a word to the wise here in case others run into the same thing.
Suppose you have
let wrapper = mount(<MyComponent />);
let mySubComponent = wrapper.find("#my-id");
mySubComponent.simulate("click");
If the click should cause a change in the sub-component, you might think that you could do
expect(mySubComponent.contains("text that appeared after click")).toEqual(true);
but that won't work. mySubComponent appears to be a static snapshot, which doesn't get updated by the simulated click, even though it was what was clicked. Instead you have to look in the original component:
expect(wrapper.contains("text that appeared after click")).toEqual(true);
@protoEvangelion
Not sure, why you have closed this issue, I can only see some workarounds here.
I have more than 200 test cases written using the mount, I can't replace them with shallow now.
I believe this "Bug" is still there.
.prop('onClick')() is the best workaround I got, but still, API supposed to work as expected i.e. simulate should work.
@ipraveen simulate has only ever been designed to be sugar around invoking a prop function - it鈥檚 simply badly named. Can you file a new issue if you鈥檙e still having trouble with something other than simulate?
I am having the same problem. With shallow I was using dive(), but with mount it does not work.
The same issue with me as well.
const wrapper = mount(<App />);
const nameInput = wrapper.ref('name');
nameInput.simulate('change', { target: { value: 'The fantastic beast' } });
Gives me the error:
TypeError: nameInput.simulate is not a function
@ankitsinghaniyaz .ref can return a component instance or a DOM node, it will never return an enzyme wrapper.
I am facing the same issue - Nested component and Redux Form
const wrap = initialWrapper();
const identifier = wrap.find("input").first();
identifier.prop("onChange")({ checked: true });
initialWrapper is a redux form and input is a radio. The props status is:
{ name: 'targetBy',
onBlur: [Function],
onChange: [Function],
onDragStart: [Function],
onDrop: [Function],
onFocus: [Function],
value: 'identifier',
checked: false,
className: 'form-check-input',
type: 'radio' }
@ljharb
How do you shallow render every component?
@HrutvikPatel add a shallow render test for each one? I鈥檓 not sure what you鈥檙e asking (you should strive for one component per file, and always have one test file per production file regardless)
@ljharb sorry, let me give you more details.
const STORE = createStore();
describe('InventoryBase', () => {
let wrapper;
let props;
let childProps;
beforeEach(() => {
props = {
inventory: inventory,
packages: packages,
branchLockers: branchLockers,
updateInventory: jest.fn(),
handleUpdate: jest.fn()
}
childProps = {
handleClick: jest.fn(),
}
wrapper = mount(
<Provider store={STORE}>
<InventoryViewComponent {...props}>
<StyledInventoryBase {...childProps}/>
</InventoryViewComponent>
</Provider> , { attachTo: document.body }
);
});
test('Should not update Last updated time if input values for in vault quanties are not changed', () => {
document.getElementById('Envelop_1').value = '2'=
console.log(wrapper.find('#UPDATE').at(0).debug());
wrapper.find('#UPDATE').at(0).simulate('click');
wrapper.update();
expect(childProps.handleClick).toHaveBeenCalledTimes(1);
expect(props.handleUpdate).toHaveBeenCalledTimes(1);
});
});
So I am trying to test a parent component InventoryViewComponent with its child StyledInventoryBase which takes the data from parent and builds the UI accordingly. I need to simulate a click in the InventoryBase and check if the function handleUpdate has been called. handleUpdate() is passed down to the child from parent. The problem is that the click is occurring but the click is not registering in the mock function, so I am getting hasBeenCalled = zero instead of once.
You should shallow render those separately. The InventoryViewComponent by itself, and the StyledInventoryBase by itself (both with Provider as a WrappingComponent if needed).
To solve this problem, in React Native context, I've used shallow method like this :
const wrapper = shallow(<MyComp />)
wrapper.find(MySubComp).shallow().simulate('press')
Most helpful comment
@mrbinky3000
.prop('onClick')()