2

J'ai un composant qui emploie sous forme modèle axé-Pourquoi la propriété ngForm "controls" est vide dans mon test? (Angulaire)

<form (ngSubmit)="onSearchCorpus(form)" #form="ngForm"> 
<combo-box [(ngModel)]="model.corpus" name="corpus" #corpus="ngModel"></combo-box> 
<input [(ngModel)]="model.label" name="label" id="label" type="text" required pattern="^(?!\s*$)[\w\_\-\:\s]*" maxlength="50" class="form-control label-name" autocomplete="off" #label="ngModel"> 
<textarea [(ngModel)]="model.query" name="query" id="query" maxlength="3600" required validateQuerySyntax class="form-control search-query" #query="ngModel" #queryControl 
     placeholder="Example: (&quot;grantee&quot; OR &quot;grant&quot; OR &quot;sponsor&quot; OR &quot;contribute&quot; OR &quot;contributor&quot;) NEAR (&quot;non-profit organization&quot; OR &quot;charities&quot;)"> 
     </textarea> 
<button [disabled]="corpusValidationInProgress" type="submit" class="button-level-one">Search</button> 
</form> 

Dans la méthode qui gère la soumission du formulaire I accès à une propriété controls d'exemple NgForm et il fonctionne très bien dans le navigateur.

onSearchCorpus(formData: NgForm) { 
    ... 
    const corpusErrors = formData.controls.corpus.errors; 
    ... 
} 

Cependant lorsque je tente de tester cette méthode avec Karma controls propriété du NgForm est vide. Je suis confus pourquoi est-ce. La méthode échoue avec l'erreur cannot read property "errors" of undefined.

Voici comment mon test ressemble à:

it('should not perform corpusSearch if selected corpus no longer exists',() => { 
    component.ngOnInit(); 
    const form = fixture.debugElement.query(By.css('form')); 
    form.triggerEventHandler('submit', null); 
    ... 
}); 

et voilà comment je suis la mise en place mon costume de test:

beforeEach(async(() => { 
    TestBed.configureTestingModule({ 
     // schemas: [NO_ERRORS_SCHEMA], 
     imports: [ 
      FormsModule, 
      PopoverModule 
     ], 
     providers: [ 
      CorpusSearchService, 
      { provide: ApiService, useValue: ApiServiceStub }, 
      { provide: Router, useClass: RouterStab }, 
     ], 
     declarations: [ 
      SearchCorpusComponent, //<--component under test 
      ComboBoxComponent //<-- 3rd party combobox which is used for first control 
     ] 
    }).compileComponents(); 
})); 

beforeEach(() => { 
    fixture = TestBed.createComponent(SearchCorpusComponent); 
    component = fixture.componentInstance; 
    apiService = fixture.debugElement.injector.get(ApiService); 
    subject = new Subject(); 
}); 

Alors, pourquoi controls est vide dans un environnement de test?

Répondre

2

La raison pour laquelle controls est "vide" dans l'environnement de test est que les contrôles n'ont pas encore été initialisés dans l'environnement de test au moment de l'appel onSearchCorpus.

J'ai préparé un Plunkr (voir form.component.spec fichier) qui illustre ce problème. Dans le même fichier, il existe également une solution de travail.

Donc, en résumé, pour que cela fonctionne, vous devez utiliser le mécanisme fakeAsync.

Ainsi, au lieu de:

it('testing form the wrong way',() => { 

    fixture.detectChanges(); 

    comp.onSubmit(); // Validates and submits a form 

    expect(comp.submitted).toEqual(false); 
    }); 

vous devez écrire un test comme:

it('testing form the proper way', fakeAsync(() => { 

    // This first detectChanges is necessary to properly set up the form 
    fixture.detectChanges(); 

    // Tick needs to be called in order for form controls to be registered properly. 
    tick(); 

    comp.onSubmit(); // Validates and submits a form 

    expect(comp.submitted).toEqual(false); 

    }));