(Angular)Karma Jasmine测试显示一个正常的功能失败。

huangapple go评论75阅读模式
英文:

(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.

huangapple
  • 本文由 发表于 2023年7月6日 18:44:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76627993.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定