来自另一个组件的角度测试输入组件

时间:2018-10-04 18:48:19

标签: javascript angular karma-jasmine

我是Angular的初学者。

我用Angular Bootstrap创建了一个简单的应用程序,它打开了一个简单的模态。

在继续之前,我想实现我的测试。

我的问题:

我想为MainComponent测试此工作流程:

  • 单击按钮openModal(或调用openModal)
  • 验证此模式的所有内容
  • 模拟/单击关闭并关闭,并验证我的功能 调用getDismissReason和closeModal。

我的问题:

第一季度

执行时:

expect(modalService.open).toHaveBeenCalled();

如何确定模式是真正开放的还是函数真正被调用的?

第二季度:

当我尝试此代码时:

const h4DebEl : DebugElement = fixtureMainComponent.debugElement.query(By.css('h4'));

为什么它为空?

我认为是因为H4标签位于ModalComponent的元素中。

然后,我进行了测试:

fixtureModalComponent = TestBed.createComponent(ModalComponentComponent);

但是我有一个activeModal的错误提供程序...

请在下面找到我的实际代码:

MainComponentComponent.component.ts

import { Component, OnInit } from '@angular/core';
import { NgbModal, ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap';

import { ModalComponentComponent } from '../modal-component/modal-component.component';

@Component({
  selector: 'app-main-component',
  templateUrl: './main-component.component.html',
  styleUrls: ['./main-component.component.scss']
})

export class MainComponentComponent implements OnInit {

  constructor(
    // Use modalService to open a modal
    private modalService: NgbModal
  ) { }

  ngOnInit() {

  }

  openModal() {
    const modalRef = this.modalService.open(ModalComponentComponent);

    // Define the value @Input person in ModalComponentComponent
    modalRef.componentInstance.person = {
      name: "Itachi",
      lastName: "Uchiwa"
    };

    modalRef.result.then((result) => {
      this.closeModal();
    }, (reason) => {
      this.dismissReason(reason);
    });
  }

  /**
   * Close modal
   */
  closeModal() {
    console.log('Closed modal');
  }

  /**
   * Dismiss modal
   */
  dismissReason(reason: any) {
    if (reason === ModalDismissReasons.ESC) {
      this.dismissReasonEsc();
    } else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
      this.dismissReasonBackdropClick();
    } else {
      this.dismissReasonUnknownReason();
    }
  }

  dismissReasonEsc() {
    console.log('Dismiss called by pressing ESC');
  }

  dismissReasonBackdropClick() {
    console.log('Dismiss called by pressing BACKDROP_CLICK');
  }

  dismissReasonUnknownReason() {
    console.log("Dismiss called");
  }

}

MainComponentComponent.component.spec.ts

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NgbModal, NgbModalRef, ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap';
import { AppModule } from '../app.module';
import { MainComponentComponent } from './main-component.component';
import { ModalComponentComponent } from '../modal-component/modal-component.component';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

describe('MainComponentComponent', () => {
  let component: MainComponentComponent;
  // Wrapper MainComponentComponent
  let fixtureMainComponent : ComponentFixture<MainComponentComponent>;
  let modalService: NgbModal;
  let modalRef: NgbModalRef; 

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports : [ AppModule ]
    }).compileComponents().then(() => {
      modalService = TestBed.get(NgbModal);
      fixtureMainComponent = TestBed.createComponent(MainComponentComponent);
      component = fixtureMainComponent.componentInstance;
      modalRef = modalService.open(ModalComponentComponent);
      spyOn(modalService, "open").and.returnValue(modalRef);

      spyOn(component, "openModal").and.callThrough();
      spyOn(component, "dismissReason").and.callThrough();
      spyOn(component, "dismissReasonEsc").and.callThrough();
      spyOn(component, "dismissReasonBackdropClick").and.callThrough();
      spyOn(component, "dismissReasonUnknownReason").and.callThrough();
      spyOn(component, "closeModal").and.callThrough();
    });    
  }));

  afterAll(() => {
    modalService.dismissAll();
    fixtureMainComponent.destroy();
    component = null;
    modalRef.close();
    modalRef = null;
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('Open modal', () => {
    component.openModal();
    expect(modalService.open).toHaveBeenCalled();
  });

  it('Open modal with click on the button', () => {
    fixtureMainComponent.debugElement.query(By.css('#openModalBtn')).triggerEventHandler("click", null);
    fixtureMainComponent.detectChanges();
    expect(component.openModal).toHaveBeenCalled();
    expect(modalService.open).toHaveBeenCalled();
  });

  it('Check element in modal', () => {
    fixtureMainComponent.debugElement.query(By.css('#openModalBtn')).triggerEventHandler("click", null);
    fixtureMainComponent.detectChanges();
    // Return null
    const h4DebEl : DebugElement = fixtureMainComponent.debugElement.query(By.css('h4'));
    // const h4HtmlEl : HTMLElement = h4DebEl.nativeElement;
    // expect(h4element.textContent).toEqual("Header :");
  });

  /**
   * Check the dismiss method ESC 
   * To do same for BACKDROP_CLICK, ...
   */
  it('Dimiss with ESC', () => {
    component.openModal();
    modalRef.dismiss(ModalDismissReasons.ESC);
    expect(component.dismissReason).toHaveBeenCalled(); 
    expect(component.dismissReasonEsc).toHaveBeenCalled();
  });

});

ModalComponentComponent.component.ts

import { Component, Input } from '@angular/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';

@Component({
  selector: 'app-modal-component',
  template: `
  <div class="modal-header">
    <h4 class="modal-title" id="modal-basic-title">Header : {{person.lastName}} {{person.name}}</h4>
    <button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
  <div class="modal-body">
    Content modal
  </div>
  <div class="modal-footer">
    <button type="button" class="btn btn-outline-dark" (click)="activeModal.close('Save click')">Save</button>
  </div>
  `
})

export class ModalComponentComponent {
  @Input() person;
  constructor(public activeModal: NgbActiveModal) { }
}

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';

import { AppComponent } from './app.component';
import { MainComponentComponent } from './main-component/main-component.component';
import { ModalComponentComponent } from './modal-component/modal-component.component';

@NgModule({
  declarations: [
    AppComponent,
    MainComponentComponent,
    ModalComponentComponent
  ],
  imports: [
    BrowserModule,
    NgbModule.forRoot()
  ],
  providers: [],
  bootstrap: [AppComponent],
  entryComponents: [ ModalComponentComponent ],
  schemas : [ CUSTOM_ELEMENTS_SCHEMA ]
})
export class AppModule { }

感谢您的帮助和时间,

最诚挚的问候,

1 个答案:

答案 0 :(得分:0)

Q1如何确保模式是真正开放的或真正调用的函数?

  • 真正开放:您无需担心测试,应该在ng-bootstrap中进行测试
  • 或真正被调用的函数:是测试说它是打开的,然后是它的打开:)

第二季度 -调试:不知道

模拟主动模式

 const activeModal: any = jasmine.createSpyObj('activeModal', ['close', 'dismiss']);

添加到测试平台提供商

  { provide: NgbActiveModal, useValue: activeModal }