chai-enzyme
chai-enzyme copied to clipboard
some/any, every, none assertions
I'm having trouble with handling cases involving multiple nodes. My team generally doesn't like to change the source code purely for the sake of the tests, so we can't really use find
on an id
since usually we wouldn't otherwise need an id
. Therefore our tests look like this:
context('with an adminPath passed as a prop', () => {
it('renders a link to the admin page', () => {
const adminPath = '/admin';
const actual = shallow(<MyComponent {...{ adminPath }}).find({ href: adminPath });
expect(actual).to.be.present();
});
});
This works, but a failing test gives us something like "expected false to be true." We could use the enzyme helpers here such as some
or someWhere
, but those are really matchers, not assertions. We end up having to use .length.to.equal(1)
or something similar, which doesn't really convey the true meaning of the test.
I think it would be great if we could have some sort of API like this:
const adminPath = '/admin';
const actual = shallow(<MyComponent {...{ adminPath }});
expect(actual).any.to.haveAttr('href', adminPath);
The inverse would be:
const adminPath = '/admin';
const actual = shallow(<MyComponent {...{ adminPath }});
expect(actual).none.to.haveAttr('href', adminPath);
Is there an alternative that I missed?
If no, is this feasible? I would imagine it would involve somehow extending enzyme
, as this is where the non
property would have to come from. If this is possible, I'd be happy to help!
Any reason expect(actual).toHaveNodeWithAttr('href', adminPath)
and expect(actual).not.toHaveNodeWithAttr('href', adminPath)
couldn't work by adding a single invertable assertion to chai-enzyme? (altho toHaveNodeWithProp
might make more sense)
You could write a assertion with descendants
because it accepts a enzyme selector. I think the following would work:
const actual = expect(<MyComponent {...{ adminPath }}).to.have.descendants({ href: adminPath });
Although I'm not sure if href is a key or property in this case. It will only work for properties.
Besides that, if you want to do any kind of sane UI testing with Selenium you're gonna be adding those same id's & classes that would have made this unit tests easier to write. In the end the team should write testable code, having good identifiers on the elements you want to test later on is part of that.
@ljharb That seems like a good way to go as well!
@marcodejongh Whoa, this is definitely useful. I didn't think of writing it that way. Thanks! And if you and your team see no reason not to use id
s to make tests easier to write, maybe I should get my team to re-think our policy. I can definitely see how much easier these tests would be if we could just do find('#someId')
.
@robwise I think something along the lines of @ljharb's proposal would work. But it's only delaying the inevitable, unless you're absolutely sure you never want to UI test.
My only issue with id
s is that we're going back to the problem which was just solved by CSS Modules: you need to think about uniqueness of id
s.
- It's not a problem in context of component-oriented js unit testing, but it's not standard compliant in context of
document
(ok, I'm a bit pedantic here, but there is # 2). - If you're using it in unit testing, you'll be using it in integration testing, and here we have a real problem.