как вызвать замену ввода из спецификации Angular - PullRequest
0 голосов
/ 15 января 2019

У меня есть input HTML File, поданный

<input type="file" class="custom-file-input" id="question-file-upload" formControlName="image" (change)="handleFileSelect($event)">

Я хочу выполнить модульный тест handleFileSelect. Но я не знаю, как вызвать метод ввода onChange. Ниже spec я написал, но я получаю ошибку imageInputNE.onchange is not a function

fit('should keep track of image counter when an image is loaded', () => {
    let newPracticeQuestionComponent = component;
    expect(newPracticeQuestionComponent.currentImageAttachmentCount).toBe(0);
    let imageInputDE = fixture.debugElement.query(By.css("#question-file-upload"));
    expect(imageInputDE).toBeTruthy();
    spyOn(newPracticeQuestionComponent,'handleFileSelect');

    let imageInputNE:HTMLElement = imageInputDE.nativeElement as HTMLElement;
    imageInputNE.onchange(new Event("some event"));
    expect(newPracticeQuestionComponent.handleFileSelect).toHaveBeenCalled();


  });

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Исходя из другого ответа , я бы посоветовал вам изменить handleFileSelect, чтобы просто взять files.

interface File {
  // the properties you need, for example:
  name: string;
}

// You don't need all this unless you must use `item()`
// interface FileList {
//     readonly length: number;
//     item(index: number): File | null;
//     [index: number]: File;
// }
// instead, just use ArrayLike<File>
export function handleFileSelect(files: ArrayLike<File>) {
    // Write code here, for example:
    if (files.length > 0) {
        console.log(files[0].name);
    }
}

Тогда ваш тест должен быть просто:

const files = [{
  name: 'File 1'
}];
handleFileSelect(files);

И ваш компонент будет просто:

handleFileSelect(event.target.files);

Вот пример , который показывает, как оба использования не вызывают ошибку в компиляторе.

0 голосов
/ 17 января 2019

Ссылаясь на документацию на веб-сайте Mozilla, события обычно инициируются «внешними» источниками, такими как кнопки, их также можно запускать программно, например, путем вызова метода HTMLElement.click () элемента. или определив событие, а затем отправив его указанной цели с помощью EventTarget.dispatchEvent ().

Я полагаю, что click - это простое событие, которое может запускаться программно, но change Событие для <input type=file..> более сложное, так как требует выбора файла, преобразования в блог, обновления свойства files и т. Д. Итак, вероятно, по этой причине я не могу просто позвонить imageElementNE.change().

Итак, я подумал об использовании dispatchEvent, и, похоже, он работает

1) Я явно создал Событие. Я предполагаю, что конструктор Event принимает 2 аргумента, 2-й является необязательным.

С https://developer.mozilla.org/en-US/docs/Web/API/Event/Event

event = new Event(typeArg, eventInit);

Из документации typeArg - это строка DOMString, представляющая имя события. Другими словами, 1-й аргумент представляется type события. Поскольку я хочу отправить change событие, мне нужно назвать его change.

Для части eventInit я посмотрел определение события change в https://developer.mozilla.org/en-US/docs/Web/Events/change и выбрал значения bubbles и cancelable оттуда

let fileSelectEvent = new Event("change",{bubbles:true,
    cancelable: false});

Это создает Event, который выглядит следующим образом (я должен признаться, я не очень понимаю)

 Event {isTrusted: false, type: "change", target: input#question-file-upload.custom-file-input.ng-untouched.ng-pristine.ng-valid, currentTarget: input#question-file-upload.custom-file-input.ng-untouched.ng-pristine.ng-valid, eventPhase: 2, …}bubbles: truecancelBubble: falsecancelable: falsecomposed: falsecurrentTarget: nulldefaultPrevented: falseeventPhase: 0isTrusted: falsepath: (10) [input#question-file-upload.custom-file-input.ng-untouched.ng-pristine.ng-valid, div#file-upload.custom-file, div.form-group, form#new-question-form.practice-question-form.ng-untouched.ng-pristine.ng-invalid, div#form-div.body__div--background, div#root0, body, html, document, Window]returnValue: truesrcElement: input#question-file-upload.custom-file-input.ng-untouched.ng-pristine.ng-validtarget: input#question-file-upload.custom-file-input.ng-untouched.ng-pristine.ng-validtimeStamp: 3759.4000000026426type: "change"__proto__: Event

2) После создания Event я вызвал метод dispatchEvent для imageInputNE. По сравнению с EventTarget.dispatchEvent(), я думаю, это означает, что EventTarget вызывает событие (в моем случае imageInputNE запускает fileSelectEvent.

imageInputNE.dispatchEvent(fileSelectEvent);

Вся пройденная спецификация

  fit('should keep track of image counter when an image is loaded', () => {
    let newPracticeQuestionComponent = component;
    expect(newPracticeQuestionComponent.currentImageAttachmentCount).toBe(0);
    let imageInputDE = fixture.debugElement.query(By.css("#question-file-upload"));
    expect(imageInputDE).toBeTruthy();
    spyOn(newPracticeQuestionComponent,'handleFileSelect');/*.and.callThrough();/*.and.callFake((event)=>{
      console.log("fake handleFileSelect called with event",event);
    });*/
    /*
    nativeElemenet hasn'nt got any type. As this program will run in a browser, we can
    typecast it to HTMLElement so that we can access prperties and methods of the
    corresponding nativeElement

     The HTMLElement interface represents any HTML element. Some elements directly
     implement this interface, while others implement it via an interface that inherits it.
     */
    let imageInputNE = imageInputDE.nativeElement ;
    console.log("input element is ",imageInputNE);
    console.log("debug element is ",imageInputDE);
    //imageInputNE.click();
    let fileSelectEvent = new Event("change",{bubbles:true,
    cancelable: false});

    console.log("created event ",fileSelectEvent);
    imageInputNE.dispatchEvent(fileSelectEvent);

    expect(newPracticeQuestionComponent.handleFileSelect).toHaveBeenCalled();


  });

Вышеприведенное может быть не лучшим решением, так как я не могу манипулировать files в поле input, но это лучшее, что я могу придумать!

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