У меня есть компонент:
import { Component, HostBinding, Input, OnChanges, SimpleChanges } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
@Component({
selector: 'app-card',
templateUrl: 'card.component.html',
styleUrls: ['card.component.scss'],
})
export class CardComponent implements OnChanges {
@Input()
isNew = false;
@Input()
@HostBinding('class.expanded')
expanded: boolean;
@Input()
header: string;
ngOnChanges(changes: SimpleChanges): void {
if ('isNew' in changes && this.isNew === true) {
this.expanded = true;
}
}
onClick(): void {
console.log('onClick');
if (this.isNew) {
return;
}
this.expanded = !this.expanded;
}
onContentClick(e: MouseEvent): void {
e.stopPropagation();
}
}
и шаблон:
<mat-card (click)="onClick()">
<div class="header">
<span class="header-text">{{ header }}</span>
<button *ngIf="!isNew" mat-icon-button>
<mat-icon>expand_more</mat-icon>
</button>
</div>
<mat-card-content *ngIf="expanded"
(click)="onContentClick($event)">
</mat-card-content>
</mat-card>
Я пытаюсь написать модульные тесты для тестирования этого компонента, поэтому есть тест:
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { Component, DebugElement, NO_ERRORS_SCHEMA, ViewChild } from '@angular/core';
import { By } from '@angular/platform-browser';
import { CardComponent } from './card.component';
import { MatCardModule } from '@angular/material/card';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
@Component({
template: '<app-card header="Some header"><div class="content">Content text</div></app-card>',
styles: ['.content { height: 100px }'],
})
class CardWrapperComponent {
@ViewChild(CardComponent)
card: CardComponent;
}
describe('CardComponent', () => {
let wrapper: CardWrapperComponent;
let card: CardComponent;
let fixture: ComponentFixture<CardWrapperComponent>;
let de: DebugElement;
beforeEach(async () => {
fixture = TestBed.configureTestingModule({
imports: [
NoopAnimationsModule,
MatCardModule,
MatButtonModule,
MatIconModule,
],
declarations: [
CardWrapperComponent,
CardComponent,
],
schemas: [
NO_ERRORS_SCHEMA,
],
}).createComponent(CardWrapperComponent);
wrapper = fixture.componentInstance;
await fixture.detectChanges();
card = wrapper.card;
de = fixture.debugElement.query(By.directive(CardComponent));
});
it('should display a header', () => {
expect(de.nativeElement.textContent).toContain('Some header');
});
it('should not display content', () => {
expect(de.nativeElement.textContent).not.toContain('Content text');
});
fdescribe('when expand button is clicked', () => {
beforeEach(async () => {
const expandButton = de.query(By.css('button'));
expandButton.triggerEventHandler('click', undefined);
// expandButton.nativeElement.click();
await fixture.detectChanges();
});
fit('should be expanded', () => {
expect(de.nativeElement.offsetHeight).toBe(140);
});
});
});
, и есть проблема, что expandButton.triggerEventHandler('click', undefined);
не запускает обработчик onClick
. Если я использую expandButton.nativeElement.click();
, все работает хорошо.
Я не могу понять, почему это не работает. В связи с этим возникает вопрос: почему мы должны использовать абстракцию DebugElement, если она вызывает проблемы? В чем выгода? Так как модульные тесты не так просты и требуют много глубоких знаний, иногда на создание модульного теста требуется больше времени, чем на саму функциональность. Я думал, что инструменты должны облегчать и сокращать затраченное время Я вижу обратный случай, и мне нужно задать вопрос здесь, потому что случай для меня совершенно неясен.
Заранее спасибо!