英文:
(Angular) Karma Jasmine test is showing failure for a working feature
问题
你的测试代码似乎没有问题,但可能有一些异步操作导致测试失败。你可以尝试将测试的第二个it块("should show popup when clicked")更改为async/await,以确保在点击按钮后等待弹出窗口打开。例如:
it('should show popup when clicked', async () => {
let dialog: HTMLDialogElement | null = fixture.debugElement.nativeElement.querySelector("dialog");
console.log(button)
expect(dialog?.open).toBeFalse();
button.click();
await fixture.whenStable();
expect(dialog?.open).toBeTrue();
})
这应该能够更准确地测试点击按钮后是否正确显示弹出窗口。如果测试仍然失败,请检查是否有其他因素影响测试,例如可能的异步操作或定时器。
英文:
I'm trying to write a unit test for a directive that is supposed to open a popup when it's clicked.
The directive works perfectly when i test it manually, however, the unit test shows failure which I don't understand.
Test:
@Component({
template: '<button class="btn" PopupTarget target="my_modal">open modal</button>' +
'<popup popupId="my_modal">hello</popup>'
})
export class TesterComponent {
}
describe('PopupTargetDirective', () => {
let fixture: ComponentFixture<TesterComponent>
let directive: PopupTargetDirective;
let button: HTMLButtonElement;
let popup: DebugElement
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [PopupTargetDirective, TesterComponent, PopupComponent]
})
.compileComponents();
fixture = TestBed.createComponent(TesterComponent);
button = fixture.debugElement.nativeElement.querySelector(".btn")
directive = new PopupTargetDirective(new ElementRef<any>(button));
popup = fixture.debugElement.query(By.directive(PopupComponent)).nativeElement
});
it('should create an instance', () => {
expect(directive).toBeTruthy();
})
it('should show popup when clicked', () => {
let dialog: HTMLDialogElement | null = fixture.debugElement.nativeElement.querySelector("dialog")
console.log(button)
expect(dialog?.open).toBeFalse()
button.click()
fixture.whenStable().then(() => {
expect(dialog?.open).toBeTrue()
})
})
});
Directive:
@Directive({
selector: '[PopupTarget]'
})
export class PopupTargetDirective {
@Input() target : string = '';
constructor(private el: ElementRef) {
el.nativeElement.addEventListener("click", ()=>{
let targetPopup: HTMLDialogElement | null = document.getElementById(this.target) as HTMLDialogElement;
targetPopup?.showModal()
})
}
}
popup HTML:
<dialog #dialog id="{{popupId}}" class="modal tw-rounded-md"
(close)="this.onClose.emit()"
(cancel)="cancel($event)"
>
<form method="dialog" class="modal-box">
<div class="tw-flex tw-flex-col tw-justify-center">
<button #closeButton class="tw-self-end" *ngIf="showCloseButton">✕</button>
<ng-content class="tw-self-auto"></ng-content>
</div>
</form>
</dialog>
Popup ts
@Component({
selector: 'popup',
templateUrl: './popup.component.html'
})
export class PopupComponent {
@Input() showCloseButton: boolean = false;
@Input({required: true}) popupId: string | undefined;
@Output() onClose: EventEmitter<void> = new EventEmitter()
@ViewChild("dialog") dialog: ElementRef<HTMLDialogElement> | undefined
@ViewChild("closeButton") closeButton: ElementRef<HTMLButtonElement> | undefined
cancel(event: Event) {
if (!this.showCloseButton) event.preventDefault()
else
this.onClose.emit()
}
}
Is there something wrong with my test code? As I mentioned it works perfectly fine when I test it manually so this is probably the case.
答案1
得分: 0
在测试中,您需要自行调用 fixture.detectChanges()
来处理变更检测。在您的测试中,未执行任何变更检测,因此组件未初始化,也未在单击后更新。
请在 TestBed.createComponent
行之后(用于初始化组件)和 button.click()
之后(用于单击后更新视图)调用 fixture.detectChanges()
。在 button.click()
之后,再次查询对话框,现在应该可以找到它。
要调试测试,通常有助于在非无头浏览器模式下运行测试,以便您可以查看哪些组件被渲染。在 Karma 中,您可以在 karma.conf.js
文件中配置此选项。
英文:
In tests you need to take care of change detection on your own by calling fixture.detectChanges()
. In your test, there is no change detection done, so the component is not initialized, nor updated after the click.
Please call fixture.detectChanges()
after the TestBed.createComponent
line (to initialize the component) and after button.click()
(to update the view after the click). After button.click()
, query the dialog again, now it should be found.
To debug tests it is often helpful to run the test in non-headless browser mode, so that you can see which components are rendered at all. In karma you can configure this in your karma.conf.js
file.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论