简体   繁体   中英

Is there a way in angular (unit testing) to find a component by its @Input() property values?

This question refers to angular unit tests. I'm searching for a short way to find components by the values, which they receive through their @Input() data binding.

I have the following child component MyComponent . Which has an @Input() property called id`:

@Component({
    selector: 'my-component,
    template: `... something ...`
})
class MyComponent {
    @Input() id: string;
}

I use this component inside a ParentComponent and pass different ids through the @Input() property:

...
<my-component [id]="first-comp"></my-component>
<my-component [id]="second-comp"></my-component>
...

Now I have a unit test for the ParentComponent . If I want to find the two components by their id I'm doing this:

let firstComponent: MyComponent;
let secondComponent: MyComponent;

const myComponents = debugElement.query(By.css('my-component'));
for (const myComponent of myComponents) {
    if (myComponent.componentInstance.id === 'first-comp') {
        firstComponent = myComponent.componentInstance;
    } else if (myComponent.componentInstance.id === 'second-comp') {
        secondComponent = myComponent.componentInstance;
    }
}

This code is not very easy to write. Does angular provide a function like, to do this in an easier way without the for-loop? Something like this:

const firstComponent = debugElement.query(By.css('my-component[id="first-component"]'));
const secondComponent = debugElement.query(By.css('my-component[id="second-component"]'));

Thank you for your help.

Well in this case you can simply assign them with this

const [firstComponent, secondComponent] = debugElement.query(By.css('my-component'));

Which is way easier to write.

You can also CSS selectors :

    const firstComponent = debugElement.query(By.css('my-component:first-of-type'));
    const secondComponent = debugElement.query(By.css('my-component:last-of-type'));

Ok. I did found a pretty nice way. You can pass a custom function into the query function of the debugElement .

So I wrote a custom "check" function:

export function findByComponentId(id: string): (queryDebugElement: DebugElement) => boolean {
    return (queryDebugElement: DebugElement) => {
        if (queryDebugElement.componentInstance) {
            if (queryDebugElement.componentInstance.id === id) {
                return queryDebugElement.componentInstance;
            }
        }
        return false;
    };
}

And then I can easily use it like this:

const firstComponent = debugElement.query(findByComponentId('first-component'));
const secondComponent = debugElement.query(findByComponentId('second-component'));

To use it with different @Input() properties or in a more general way, you could create a more general function. So the writer of the test can define for which the component should be checked:

export function findIfMatches(check: (component: any) => boolean): (queryDebugElement: DebugElement) => boolean {
    return (queryDebugElement: DebugElement) => {
        if (queryDebugElement.componentInstance) {
            if (queryDebugElement.componentInstance.id === id) {
                return check(queryDebugElement.componentInstance);
            }
        }
        return false;
    };
}

const firstComponent = debugElement.query(findIfMatches(component => component.id === 'first-component'));
const secondComponent = debugElement.query(findIfMatches(component => component.id === 'second-component'));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM