web-dev-qa-db-fra.com

Crochet de cycle de vie d'AfterViewInit dans le test Jasmine

Je suis confus sur les crochets du cycle de vie en relation avec les tests Jasmine. Le document LifeCycle Angular ne mentionne pas les tests https://angular.io/guide/lifecycle-hooks . Le document de test ne mentionne que OnChange https: //angular.io/guide/testing . J'ai un exemple de composant comme suit:

import { Component, OnInit, AfterViewInit, OnDestroy, ElementRef } from '@angular/core';
...
@Component({
  selector: 'app-prod-category-detail',
  templateUrl: './prod-category-detail.component.html',
  styleUrls: ['./prod-category-detail.component.css']
})
//
export class ProdCategoryDetailComponent implements OnInit, AfterViewInit, OnDestroy {
    ...
    nav: HTMLSelectElement;
    //
    constructor(
        ...
        private _elementRef: ElementRef ) { }
    ...
    ngAfterViewInit() {
        console.log( 'ProdCategoryDetailComponent: ngAfterViewInit' );
        this.nav = this._elementRef.nativeElement.querySelector('#nav');
    }
    ...
}

Remarque: il s'agit d'une application CLI Angular CLI avec les derniers téléchargements. Dans Karma, je ne vois pas le journal de la console, donc nav n'est jamais défini. Je l'invoque actuellement dans mes spécifications comme suit:

beforeEach(() => {
  fixture = TestBed.createComponent(ProdCategoryDetailComponent);
  sut = fixture.componentInstance;
  sut.ngAfterViewInit( );
  fixture.detectChanges( );
});

Est-ce une bonne façon de gérer cela?

Pour Shusson, c'est il y a quelque temps et je n'ai pas regardé cela depuis un certain temps. J'espère que cela vous aidera. Remarque, j'utilise la bibliothèque Primeface de Primeface:

describe('ProdCategoryDetailComponent', () => {
  let sut: ProdCategoryDetailComponent;
  let fixture: ComponentFixture< ProdCategoryDetailComponent >;
  let alertService: AlertsService;
  let prodCatService: ProdCategoryServiceMock;
  let confirmService: ConfirmationServiceMock;
  let elementRef: MockElementRef;
  //
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        FormsModule,
        ButtonModule,
        BrowserAnimationsModule
      ],
      declarations: [
        ProdCategoryDetailComponent,
        AlertsComponent,
        ConfirmDialog
      ],
      providers: [
        AlertsService,
        { provide: ProdCategoryService, useClass: ProdCategoryServiceMock },
        { provide: MockBackend, useClass: MockBackend },
        { provide: BaseRequestOptions, useClass: BaseRequestOptions },
        { provide: ConfirmationService, useClass: ConfirmationServiceMock },
        { provide: ElementRef, useClass: MockElementRef }
      ]
    })
    .compileComponents();
  }));
  //
  beforeEach(inject([AlertsService, ProdCategoryService,
      ConfirmationService, ElementRef],
        (srvc: AlertsService, pcsm: ProdCategoryServiceMock,
        cs: ConfirmationServiceMock, er: MockElementRef) => {
    alertService = srvc;
    prodCatService = pcsm;
    confirmService = cs;
    elementRef = er;
  }));
  //
  beforeEach(() => {
    fixture = TestBed.createComponent(ProdCategoryDetailComponent);
    sut = fixture.componentInstance;
    sut.ngAfterViewInit( );
    fixture.detectChanges( );
  });
  //
12
P. Huhn

J'appelle souvent directement les crochets du cycle de vie de chaque spécification chaque fois que nécessaire. Et ça marche. Parce que cela donne la flexibilité de manipuler toutes les données avant d'appeler ngAfterViewInit() ou ngOnInit().

J'ai également vu quelques angular bibliothèques testent les spécifications en les utilisant de la même manière. Par exemple, vérifiez ce videogular fichier de spécifications. Il n'y a donc aucun mal à appeler ces méthodes manuellement.

Copiez également le même code ici, juste pour éviter que le lien ne soit rompu à l'avenir.

it('Should hide controls after view init', () => {
        spyOn(controls, 'hide').and.callFake(() => {});

        controls.vgAutohide = true;

        controls.ngAfterViewInit();

        expect(controls.hide).toHaveBeenCalled();
});
2
Amit Chigadani

Nous ne pouvons pas appeler directement les hooks du cycle de vie à partir de spec, mais nous pouvons appeler des méthodes personnalisées. Parce que pour appeler des livres de cycle de vie, nous devons créer une instance du composant à l'aide de fixture.

Exemple: dans mon exemple, je dois définir padding-left et right à 0 comme bootstrap donne un peu de rembourrage gauche et droite par défaut, donc je dois le supprimer. =

Fichier HTML - app.component.ts

import { Component, ViewChild, ElementRef, Renderer2 } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  @ViewChild('navCol', { static: true }) navCol: ElementRef;

  constructor(private renderer: Renderer2) {  }

  ngAfterViewInit() {
    this.renderer.setStyle(this.navCol.nativeElement, 'padding-left', '0px');
    this.renderer.setStyle(this.navCol.nativeElement, 'padding-right', '0px');
  }
}

app.component.spec.ts

import { TestBed, async } from '@angular/core/testing';

describe('AppComponent', () => {
  it('should load page and remove padding', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.componentInstance.ngAfterViewInit();
    const styles = window.getComputedStyle(fixture.nativeElement);

    expect(styles.paddingLeft).toBe('0px');
    expect(styles.paddingRight).toBe('0px');
  });
});
0
Sahil Shikalgar