我也有使用引导程序的模态组件。 在这些功能中,我有一个@ContentChildren用于CloseModalDirective指令,该指令使任何元素在单击时负责关闭模式。 问题是我无法测试此功能。
该组件在应用程序中可以正常运行,我的问题仅在于测试
这是我的组件:
import {
AfterContentInit,
Component,
ContentChildren,
Directive,
ElementRef, EventEmitter,
Input,
OnDestroy,
Output,
QueryList,
ViewChild
} from '@angular/core';
import $ from 'jquery';
import ModalSizes from './modal-size.enum';
@Directive({ selector: '[appCloseModal]' })
export class CloseModalDirective {}
@Component({
selector: 'app-modal',
templateUrl: './modal.component.html',
styleUrls: ['./modal.component.scss']
})
export class ModalComponent implements AfterContentInit, OnDestroy {
@Input() header: string;
@Input() size = ModalSizes.Medium;
@Input() closeable = true;
@Output() openFinished = new EventEmitter();
@Output() closeFinished = new EventEmitter();
@ViewChild('modal') modal: ElementRef;
// FINDING MY ELEMENTS
@ContentChildren(CloseModalDirective, { descendants: true, read: ElementRef })
closeButtons: QueryList<ElementRef> = new QueryList();
show() {
$(this.modal.nativeElement).modal({
backdrop: this.closeable ? true : 'static',
keyboard: this.closeable,
show: true
});
}
hide() {
$(this.modal.nativeElement).modal('hide');
}
ngAfterContentInit() {
$(this.modal.nativeElement).on('shown.bs.modal', () => {
this.openFinished.emit();
});
$(this.modal.nativeElement).on('hide.bs.modal', () => {
this.closeFinished.emit();
});
// ADDING HIDE EVENT
this.closeButtons.forEach(button => {
button.nativeElement.addEventListener('click', this.hide.bind(this), false);
});
}
ngOnDestroy() {
$(this.modal.nativeElement).off('shown.bs.modal');
$(this.modal.nativeElement).off('hide.bs.modal');
this.closeButtons.forEach(button => {
button.nativeElement.removeEventListener('click', this.hide.bind(this));
});
$(this.modal.nativeElement).modal('dispose');
}
}
这是我的测试:
import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
import {CloseModalDirective, ModalComponent} from './modal.component';
import {Component} from '@angular/core';
import ModalSize from './modal-size.enum';
import 'bootstrap';
@Component({
selector: 'app-test',
template: `
<app-modal header="Title">
<div class="content">Content</div>
<button appCloseModal footer>Close</button>
</app-modal>
`
})
class TestComponent {}
describe('ModalComponent', () => {
let component: ModalComponent;
let fixture: ComponentFixture<ModalComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CloseModalDirective, ModalComponent, TestComponent ],
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ModalComponent);
component = fixture.componentInstance;
component.header = 'Titulo';
component.size = ModalSize.Small;
component.closeable = true;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should display title and size', () => {
const title = fixture.nativeElement.querySelector('.modal-title');
expect(title.textContent).toBe(component.header);
const classes = fixture.nativeElement.querySelector('.modal-dialog').classList;
expect(classes).toContain(component.size);
});
it('should show the modal on call show method', fakeAsync(() => {
component.show();
tick(1000);
const modal = fixture.nativeElement.querySelector('.modal');
expect(modal.classList).toContain('show');
component.hide();
tick(1000);
}));
// NOT WORKING!
it('should hide modal on click elements with appCloseModal directive', () => {
spyOn(component, 'hide');
const testFixture: ComponentFixture<TestComponent> = TestBed.createComponent(TestComponent);
const element = testFixture.nativeElement.querySelector('[appCloseModal]');
element.click();
expect(component.hide).toHaveBeenCalled();
});
});
我做错了什么?
答案 0 :(得分:0)
最后,我遇到两个问题:
testFixture.detectChanges()
。spyOn
添加到component.hide
,但是this.hide.bind(this)
覆盖了它并破坏了我的测试(添加spyOn(ModalComponent.prototype, 'hide')
解决了我的问题)