15 votes

Pas d'accesseur de valeur pour le contrôle de formulaire avec nom... pour les contrôles mat-sélectifs

Je fais des tests unitaires avec jasmin y karma pour un angulaire 6 qui valide si un formGroup est valide. Je rencontre des problèmes avec le contrôle mat-select. Lorsque j'exécute le scénario de test, Karma me renvoie une erreur disant Error: No value accessor for form control with name: 'importId' . D'ailleurs, le composant fonctionne bien, comme je m'y attendais.

enter image description here

C'est mon composant :

import {Component, Inject, OnInit} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material";
import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";

@Component({
  selector: 'app-my-component',
  templateUrl: './my.component.html',
  styleUrls: ['./my.component.css']
})
export class MyComponent implements OnInit {
  modelForm: FormGroup;
  imps;
constructor(
    public dialogRef: MatDialogRef<MyComponent>,
    @Inject(MAT_DIALOG_DATA) public data: any) {
      this.imps = data['imp'];
  }

  ngOnInit() {
    this.modelForm = new FormGroup({
      name: new FormControl(null, Validators.required),
      importId: new FormControl(null, Validators.required),
    });
  }
}

Mon modèle HTML ressemble à ceci :

<mat-dialog-content>
  <form [formGroup]="modelForm">

    <mat-form-field>
      <input matInput
             placeholder="Name"
             formControlName="name">
    </mat-form-field>

    <mat-form-field>
      <mat-select placeholder="Source import"
                  formControlName="importId">
        <mat-option *ngFor="let imp of imps" [value]="imp.uuid">
          {{imp.label}}
        </mat-option>
      </mat-select>
    </mat-form-field>

  </form>
</mat-dialog-content>

<mat-dialog-actions>
  <button mat-raised-button color="primary" [disabled]="!modelForm.valid" (click)="someFakeFunction()">Create</button>
  <button mat-raised-button (click)="dialogRef.close()">Cancel</button>
</mat-dialog-actions>

Enfin, voici mon test unitaire :

import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {MockMatDialogData, MockMatDialogRef} from '@testing/mock/material';
import {MyComponent} from './evaluation-wizard.component';
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material";
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {NO_ERRORS_SCHEMA} from "@angular/core";

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [MyComponent],
      imports: [ReactiveFormsModule, FormsModule],
      providers: [
        {provide: MatDialogRef, useValue: MockMatDialogRef},
        {provide: MAT_DIALOG_DATA, useClass: MockMatDialogData}
      ],
      schemas: [NO_ERRORS_SCHEMA],
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    component.ngOnInit();
    fixture.detectChanges();
  });

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

  describe('Form validation', () => {
    it('form invalid when empty ', function () {
      expect(component.modelForm.valid).toBeFalsy();
    });

    it('name field validity ', () => {
      let name = component.modelForm.controls['name'];
      expect(name.valid).toBeFalsy();

      let errors = {};
      errors = name.errors || {};
      expect(errors['required']).toBeTruthy();

      name.setValue("test");
      errors = name.errors || {};
      expect(errors['required']).toBeTruthy();
    });

  });
});

Je n'arrive pas à le faire fonctionner, des suggestions sur ce qui m'échappe ?

26voto

JB Nizet Points 250258

Vous n'importez pas les modules matériels dans votre module de test.

Alors mat-form-field , mat-select etc. sont simplement traités comme des éléments inconnus par Angular (puisque vous lui avez demandé de le faire en utilisant l'option NO_ERRORS_SCHEMA ).

1voto

Janos Vinceller Points 11

Je pense qu'il vous manque certains modules importants, c'est pourquoi ils ne sont pas connus du compilateur Angular. Mettez au moins les suivants (et plus je suppose) dans vos importations :

imports: [ReactiveFormsModule, FormsModule,
  BrowserModule,
  BrowserAnimationsModule,
  MatSelectModule,
  MatOptionModule,
  MatInputModule
],

Utilisez également

schemas: [CUSTOM_ELEMENTS_SCHEMA],

pour indiquer au compilateur qu'il doit être capable de détecter les balises non-HTML.

Avec cette réparation, vous n'aurez pas besoin de la NO_ERRORS_SCHEMA qui ne doit PAS être utilisé dans ces cas simples.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X