Компонент автозаполнения Angular2 + jquery: невозможно вызвать методы компонента внутри файла спецификации

У меня есть метод автозаполнения jquery, который используется внутри angular2, который вызывает службу для извлечения данных из api. Вот myComponent.ts:

export class myComponent {
private myVar;
private binding1;
private binding2;
constructor( @Inject(ElementRef) private elementRef: ElementRef,private _myService: MyService) {

}
public method1() { return this.myVar.val().toUpperCase(); }
public method2() { return this.myVar.val(""); }

private ngOnInit() {
    var _this = this;
    this.myVar = $(this.elementRef.nativeElement).children().eq(0).autocomplete({
        source: function(request,callback){
            _this.mainMethod(request,callback);
        },
delay:0,
select: (event, ui) => {
// …},
open: function(e,ui)
{
    //…
},
appendTo: $('body')
});

//renderMethod add data to the view using $().append()

public mainMethod (res, callback) { //gets called from inside autocomplete
if(condition 1) {
//renders data from service by calling methodOnService()
//returns binding1 and binding2  which gets rendered in view (see html)
}
else {
//call anotherMethod();
//sets binding1 and binding2  which gets rendered in view (see html)

}
}
public anotherMethod() {
//…
}

myComponent.html:

<input type="text" value="{{binding1}}" size="{{binding2}}" maxlength="94"><span></span>

Мне сложно протестировать код, так как он смешивает angular с jquery (я знаю, что это нехорошо). Но прямо сейчас я хочу вызвать method1, method2, mainMethod, anotherMethod из моего тестового файла, чтобы получить больше покрытия кода.

Файл myComponent.spec.ts:

fit(‘my component test file’,inject([TestComponentBuilder, MyComponent, ElementRef], (tcb:TestComponentBuilder) => {
        tcb.createAsync(MyComponent)
            .then((fixture) => {

                const element = fixture.debugElement.nativeElement;
                const instance = fixture.componentInstance;
                console.log("component instance", fixture.componentInstance);
                fixture.componentInstance.binding2 =12;
                fixture.componentInstance.binding1 = 'aapl';

                spyOn(instance, "methodOnService");
                spyOn(instance,"anotherMethod");
                fixture.detectChanges(); //while debugging, it invokes 'ngOnInit' method but doesn't invoke autocomplete method
                fixture.componentInstance.symbol= 'aa';
                fixture.componentInstance.binding2 =12;
                fixture.detectChanges(); //it doesn't even invoke 'ngOnInit'


                 expect(instance.methodOnService.calls.any()).toEqual(true); //error : Expected false to equal true
                expect(instance.anotherMethod).toHaveBeenCalled();
// error :Expected spy anotherMethod to have been called.

Даже для вызова method1 и method2 я не могу издеваться над this.myVar в спецификации? как мне подойти к тестированию различных методов?


person candidJ    schedule 09.06.2016    source источник
comment
Что вы имеете в виду, говоря, this.myVar высмеивая то, чего вы пытаетесь достичь?   -  person Günter Zöchbauer    schedule 10.06.2016
comment
this.myVar хранит объект jQuery и при вызове method1 в файле спецификации сообщает, что не может найти .val() неопределенного значения. так что this.myVar не издеваются   -  person candidJ    schedule 10.06.2016
comment
Над чем издеваются? Почему вы ожидаете, что над ним будут издеваться?   -  person Günter Zöchbauer    schedule 10.06.2016
comment
Я просто хочу вызватьmethod1 в файле спецификации. Под издевательством я имел в виду, что он содержит объект jQuery, возвращенный в ngOnInit. Я обновил свой файл спецификации. Теперь у вас возникла проблема?   -  person candidJ    schedule 10.06.2016
comment
Я не вижу, чтобы вы делали что-либо, что могло бы стать причиной издевательства над myVar или method1. Я не понимаю: - /   -  person Günter Zöchbauer    schedule 10.06.2016
comment
ты прав. Оставьте method1 на данный момент. Можете ли вы указать, почему я не могу вызвать метод автозаполнения при обнаружении второго изменения. (прочтите мои комментарии в файле спецификации)   -  person candidJ    schedule 10.06.2016
comment
ngOnInit() не должен вызываться каждым fixture.detectChanges(). fixture.detectChanges() - это просто вручную вызвать обнаружение изменений Angulars, которое обычно выполняется автоматически (при любом событии или асинхронном вызове). ngOnInit() вызывается только один раз после обнаружения первого изменения. Вам нужно будет уничтожить и воссоздать тестовый компонент, чтобы ngOnInit() снова был вызван.   -  person Günter Zöchbauer    schedule 10.06.2016
comment
Спасибо!! Я попробую это. Не могли бы вы дать какую-нибудь полезную ссылку, которая могла бы быть полезной?   -  person candidJ    schedule 10.06.2016
comment
Полезная ссылка для тестирования? Просто angular.io, я не знаю, публиковали ли они что-нибудь о тестировании. Последний раз проверял было не очень, но над документами постоянно работают.   -  person Günter Zöchbauer    schedule 10.06.2016
comment
если я создал экземпляр компонента с помощью TestComponentBuilder.createAsync (), то как удалить его и создать новый?   -  person DDave    schedule 10.06.2016


Ответы (1)


На самом деле это не ответ (не совсем понимаю проблему), но некоторые предложения (см. Комментарии в коде):

export class myComponent {
  private myVar;
  private binding1;
  private binding2;

  // remove `@Inject(ElementRef)` because it's redundant whent the type is
  // also `ElementRef`
  constructor(private elementRef: ElementRef,private _myService: MyService) {
  }

  public method1() { return this. myVar.val().toUpperCase(); }
  public method2() { return this. myVar.val(""); }

  private ngOnInit() {
    //var _this = this;
    this.myVar = $(this.elementRef.nativeElement).children().eq(0).autocomplete({
        source: (request,callback) => { // <<=== use arrow instead of `function`
            this.mainMethod(request,callback);
        },
    delay:0,
    select: (event, ui) => {
    // …},
    open: (e,ui) => { // <<=== use arrow instead of function
      //…
    },
    appendTo: $('body')
  });

  //renderMethod add data to the view using $().append()

  public mainMethod(res, callback) { //gets called from inside autocomplete
    if(condition 1) {
      //renders data from service by calling methodOnService()
      //returns binding1 and binding2  which gets rendered in view (see html)
    } else {
      //call anotherMethod();
      //sets binding1 and binding2  which gets rendered in view (see html)
    }
  }

  public anotherMethod() {
  //…
  }
}
person Günter Zöchbauer    schedule 10.06.2016