Угловой тестовый компонент ввода из другого компонента - PullRequest
0 голосов
/ 04 октября 2018

Я новичок в Angular.

Я создал простое приложение с Angular Bootstrap, которое открывает простой модальный режим.

Прежде чем продолжить, я хочу реализовать свои тесты.

Мои проблемы:

Я хотел бы проверить этот рабочий процесс для MainComponent:

  • Нажмите на кнопку openModal (или вызовите openModal)
  • Проверьте все содержимое этого модального
  • Имитируйте / нажмите на dismiss и close и убедитесь, что мои функции getDismissReason и closeModal вызваны.

Мои вопросы:

Q1

Когда мы выполняем:

expect(modalService.open).toHaveBeenCalled();

Как быть уверенным, что модал действительно открыт или функция действительно вызвана?

Q2:

Когда я пробую этот код:

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 голосов
/ 04 октября 2018

Q1 Как быть уверенным, что модал действительно открыт или действительно вызвана функция?

  • действительно открыт: не проблема вашего теста, должен быть протестирован в ng-bootstrap
  • или действительно вызванная функция: тест говорит, что он открыт, а затем его открыт:)

Q2 - отладка: не знаю

Mock activemodal

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

Добавить к тестовому провайдеру

  { provide: NgbActiveModal, useValue: activeModal }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...