How to find an element by its text in Enzyme?
Asked Answered
S

6

27

I have multiple buttons on my page:

<div>
    <h1>Home</h1>
    <button>Action 1</button>
    <button>Action 2</button>
</div>

How can I select the "Action 2" button by its text, so that I can click on it? I know that there may be other ways to select that button, but I am specifically looking for the best way to select an element by its text.

One way I have found is shown below. Is there a better way?

const action2Button = wrapper.find('button[children="Action 2"]');
expect(action2Button).toHaveLength(1);
action2Button.simulate('click');
Spencerianism answered 20/5, 2019 at 20:57 Comment(0)
H
17

The best way I can find to do this, so far, is the following:

const button = wrapper.findWhere(node => {
  return (
    node.type() &&
    node.name() &&
    node.text() === "Action 2"
  );
});

There must be a name, and a type, to prevent finding a text node.

I'm sure that there must be a better way to do this.

Updated: I'm not sure if Enzyme has changed since I answered this. I see that you can now avoid a text node by checking that node.type() is not undefined. I'm not sure how you would avoid a parent node with the same text though.

Humphreys answered 23/9, 2019 at 11:11 Comment(0)
B
18

Basing my answer on this blog :

https://blog.sapegin.me/all/react-testing-2-jest-and-enzyme/

I think the simplest answer is this

const action2Button = wrapper.find({children: "Action 2"})

I believe this method uses the Enzyme Object Property Selector https://enzymejs.github.io/enzyme/docs/api/selector.html#4-object-property-selector

Blithe answered 14/12, 2020 at 10:30 Comment(1)
This is such a great solution. Thank you :)Justify
H
17

The best way I can find to do this, so far, is the following:

const button = wrapper.findWhere(node => {
  return (
    node.type() &&
    node.name() &&
    node.text() === "Action 2"
  );
});

There must be a name, and a type, to prevent finding a text node.

I'm sure that there must be a better way to do this.

Updated: I'm not sure if Enzyme has changed since I answered this. I see that you can now avoid a text node by checking that node.type() is not undefined. I'm not sure how you would avoid a parent node with the same text though.

Humphreys answered 23/9, 2019 at 11:11 Comment(0)
U
14

The accepted answer didn't work for me as well - it looks like at least type should be specified in predicate statement.

So the following one is working for me:

const button = wrapper.findWhere(node => {
  return node.type() === 'button' && node.text() === 'Action 2';
});

But I'm not sure if this solution is better than the one initially proposed by author.

Undecided answered 26/11, 2020 at 9:31 Comment(1)
I think it is better than the attempt in the O.P. You would need to know the element type as well as the text though.Humphreys
C
2

I was searching for help with this today too and the solution for selecting and clicking I found (applied to this code) was:

const action2Button = wrapper.find('button').findWhere(node => node.text() === "Action 2");
expect(action2Button).toHaveLength(1);
action2Button.simulate('click');
Chemash answered 17/5, 2022 at 15:23 Comment(0)
M
1

You can get the last button using

const actionTwoButton = wrapper.find('button').Last();

This approach is only good if you have very few buttons (less than 3).

The solution by Dzmitry Alifer is more scalable.

Machination answered 30/6, 2022 at 5:5 Comment(0)
H
-1

The accepted answer didn't work for me because the node.children().length returns 1, which I'm assuming is because it's a text node, because node.children()[0] is undefined. 🤷‍♂️

const button = wrapper.findWhere(node => (
  node.name() === 'button'
  && node.children().length === 1
  && node.children()[0] === undefined
  && node.text() === 'Action 2'
));
Helotism answered 4/6, 2020 at 22:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.