Skip to content

at() should return an ErrorWrapper when wrappers is empty #1633

@angelogulina

Description

@angelogulina

What problem does this feature solve?

Situation

The component (Component) has children components (Child), one and one only of type X that is conditionally rendered.
I need to test this component in severaI cases and so it's common to retrieve the component like this:

const findX = wrapper.findAll(Child).filter(isX).at(0);

Complication

I know the element is rendered conditionally, so I want to test the case when this element does not exist. But when I try:

expect(findX().exists()).toBe(false);

surprisingly enough, I get the following error no item exists at 0.

I know the option would be not to add at(0) to my findX() method. But that's not what I would expect form a method that applies to an Array, for the following reasons:

A) The signature

at() is defined as at(index: number): Wrapper<V>;. Throwing clearly does not mean the signature is wrong but what I argue is that the error is thrown for the wrong reason.

B) The semantics

If I change the case slightly and now I have only one Child component, I could write findX() as findComponent(Child). Testing the case where it is not rendered I would be able to use exists() properly. It seems to me there is nothing inherently wrong though in sticking to the wrapper.findAll(Child).filter(isX).at(0) implementation also when I only have one Child component. Therefore I would expect the same result, that is a BaseWrapper to which I could ask if the element exists or not;

C) The similarity with filter()

Not only my findX() implementation is contingent but also at()'s one. It could easily be implemented as a filter function on the given index as they're both trying to individuate an element in an array based on some condition:

wrapper.filter((_, index) => index === 0)

In this case, if the predicate fails to verify for every element, I would get an empty array.

Returning an empty array from at() is not what we want – at() seems to be somehow similar to Array.prototype.find which would, in the case explored here, return undefined.

Solution

Given find() is already taken and that we do not want to return undefined, my proposal is to return an ErrorWrapper on which I could call the exists() method as easily as when I do it with find().

What does the proposed API look like?

The API of at() would not change, instead its internal implementation would.
It could be something along the lines of:

at(index) {
    const normalizedIndex = index < 0 ? this.length
    return this.wrappers[normalizedIndex] || new ErrorWrapper('')
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions