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.