Angular 9 Тест Карма-Жасмин не работает должным образом с ViewChild - PullRequest
0 голосов
/ 22 апреля 2020

Я использую Жасмин для тестирования моего приложения в Angular9. У меня проблема с выполнением теста, который должен работать. У меня есть файл "book-edit.component. html", который содержит представление страницы, которую я хочу протестировать, и, в частности, эту часть:

<form *ngIf='activeForm == "templateDriven"' #templateForm='ngForm'>
    <div class="row mt-3">
        <div class="col-6">
            Template-Driven Form
        </div>
    </div>
    <!-- "touched" indicates modified -->
    <div class="row">
        <div class="col-12 form-group title-group">
            <label for="title">Title</label>
            <input [(ngModel)]='book.title' name='title2' type='text' id='title2' class='title form-control'
                #title2='ngModel' minlength='3' required>
            <!-- in order to prevent an error signal in case of title2 is invalid, is useful to check that client have touch that 
            filed. Initially title2 condition are not valid, but just because client doesn't touch that field. For this reason it
            in enough to add AND clause in with we can check that that field is dirty(when a client text into that field) or toched
            anyay () (AND invalid). Thus, if it is invalid it show the parent div. In a more specific way, it will visualize the child
            div based on the type of error (required or minlenght) -->
            <div *ngIf='!title2.valid && (title2.dirty || title2.touched)' class='invalid-feedback'
                style='display: block;'>
                <div *ngIf='title2?.errors?.required'>
                    Title is required.
                </div>
                <div *ngIf='title2?.errors?.minlength'>
                    Title must have at least 3 characters long.
                </div>
            </div>
        </div>

Я хочу протестировать эту часть кода: в случае, если title2 содержит менее 3 букв, это выдает ошибку (и это работает, я пробовал без тестов). Поэтому я хотел бы довериться этому, используя такой тест (book-edit.component.spe c .ts ":

  it('should have title error if less than 3 symbols provided',
    fakeAsync(() => {
      component.activeForm = 'templateDriven';
      fixture.detectChanges();
      // get our form on the page by using templateForm. To do this add @ViewChild(NgForm) in book-edit.component.ts
      let form = component.templateForm.form;
      // tick() to say to other engine to go ahead and apply the separtions
      tick();
      form.setValue({
        title2: 'te',
        image2: 'http://test.com',
        description2: 'none',
        price2: 100
      });
      form.controls.title2.markAsTouched();
      debugger;
      //expect(form.controls.title2.errors).toBeTruthy();
      expect(nativeElement.querySelector('.title-group').textContent).
        toContain('Title must have at least 3 characters long.');
    })
  );

, имеющий следующий компонент (book-edit.component.ts):

import { Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { FormBuilder, FormGroup, Validators, AbstractControl, FormControl, NgForm } from '@angular/forms';

import { BookModel } from "../../models/book/book.model";

@Component({
  selector: 'book-edit',
  templateUrl: './book-edit.component.html',
  styleUrls: ['./book-edit.component.css']
})
export class BookEditComponent implements OnInit {
  bookEditForm: FormGroup;
  book: BookModel;
  activeForm: string = 'reactive';
  // ViewChild: Property decorator that configures a view query.
  // The change detector looks for the first element or the directive matching the selector in the view DOM. If the view DOM changes, and a new child matches the selector, the property is updated.
  @ViewChild(NgForm) templateForm: NgForm;

  constructor(fb: FormBuilder, private route: ActivatedRoute) {
    this.bookEditForm = fb.group({
      //define a group and optionally defide if it is required
      title: ['', Validators.required],
      image: ['', Validators.required],
      description: [''],
      price: ['']
    });
    // subscribe to some changes
    route.params.subscribe(res => {
      if(this.book == null){
        this.book = new BookModel('','','',0);
      }
    })
   }

  submitReactiveForm() {
    let bookData = this.prepareSaveBook();
    this.book = new BookModel(bookData.image,
      bookData.title,
      bookData.description,
      bookData.price
    );
    this.book.save();
  }

  prepareSaveBook() {
    const formModel = this.bookEditForm.value;
    return formModel;
  }

  ngOnInit(): void {
  }

}

Конечно, я поставил "@ViewChild", чтобы тест мог обнаруживать изменения в форме. На самом деле, в тесте я пытаюсь ввести имя, содержащее не более 3 букв, просто для проверки наличия ошибки и сообщения «Заголовок должен содержать не менее 3 символов». появляется. Таким образом, в конце я попытался expect(nativeElement.querySelector('.title-group').textContent).toContain('Title must have at least 3 characters long.'); проверить, содержит ли теперь мой основной div (в book-edit.component. html) также сообщение об ошибке, потому что * ngIf удовлетворены, но нет. Это не работает, и консоль записывает только значение «Test» (текст ясно через этот div) вместо «TestTitle должен иметь длину не менее 3 символов». Я перезаписал код и проверил, что форма правильно инициализирована (title2: "te", title2 затронут и title2 недействителен), но кажется, что он не может прочитать содержимое div, разблокированного * ngIf, и я не знать причину, по которой

...