1

我正在努力为我的自定义 ng-select 组件编写适当的测试。该组件按预期工作,但我很难尝试对其进行测试并且找不到解决方案。尝试了多种方法来解决错误,但Error: 1 timer(s) still in the queue. 在选择选项后我一直在继续。任何帮助,将不胜感激。

Component

@Component({
  selector: 'dp-auto-complete',
  templateUrl: './auto-complete.component.html',
  styleUrls: ['./auto-complete.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => AutoCompleteComponent),
      multi: true
    }
  ]
})
export class AutoCompleteComponent implements OnInit, OnDestroy, ControlValueAccessor {

  @Input() apiMethod: string;
  @Input() placeholder: string;
  @Input() labelProps: string[];
  @Input() callApi = true;
  @Output() selectedItem = new EventEmitter<any>();

  loading = false;
  selected: any;
  disabled: boolean;
  items$: Observable<any>;
  input$ = new BehaviorSubject('');

  constructor(private api: ApiService) {
  }

  ngOnInit() {
    this.placeholder = this.placeholder || 'Select items';
    if (this.callApi) {
      this.onSearch();
    }
  }

  ngOnDestroy() {
    this.input$.complete();
  }

  setDisabledState(isDisabled: boolean) {
    this.disabled = isDisabled;
  }

  registerOnTouched() {
  }

  registerOnChange(fn: any) {
    this.propagateChange = fn;
  }

  writeValue(value: any = null) {
    this.selected = value;
  }

  private propagateChange = (_: any) => {};

  onSearch() {
    this.items$ = concat(
      of([]),
      this.input$.pipe(
        debounceTime(300),
        tap(() => this.loading = true),
        switchMap(term => this.callService(term).pipe(
          catchError(() => of([])),
          tap(() => this.loading = false)
        ))
      )
    );
  }

  private callService(term: string) {
    return this.api[this.apiMethod](term).pipe(map((item: any) => item.results));
  }

  propagateSelected() {
    this.propagateChange(this.selected);
    this.selectedItem.emit(this.selected);
  }
}

Template

<ng-select
    [items]="items$ | async"
    [loading]="loading"
    placeholder="{{placeholder}}"
    [typeahead]="input$"
    [(ngModel)]="selected"
    (change)="propagateSelected()"
    [disabled]="disabled">

  <ng-template ng-label-tmp ng-option-tmp let-item="item">
    <div *ngFor="let label of labelProps" class="d-inline">
      {{item[label]}}
    </div>
  </ng-template>
</ng-select>

Integration TEST

beforeEach(() => {
    apiServiceStub = jasmine.createSpyObj('ApiService', ['searchOrganizations', 'getUser', 'createUser', 'updateUser']);
    apiServiceStub.searchOrganizations.and.returnValue(of({results: [
        {name: 'abc'},
        {name: 'abc123'},
        {name: 'ghc'}
      ]}));

    TestBed.configureTestingModule({
      declarations: [AutoCompleteComponent],
      imports: [FormsModule, NgSelectModule],
      providers: [
        { provide: ApiService, useValue: apiServiceStub }
      ]
    }).compileComponents();
  });

  beforeEach(() => {
    createComponent();
    component.apiMethod = 'searchOrganizations';
    component.labelProps = ['name'];
  });
  it('should ', fakeAsync(() => {
    fixture.detectChanges()
    tick(500)
    fixture.detectChanges()
    selectOption2(fixture, 38, 1)
    tick(500)
    fixture.detectChanges()

    console.log(component.selected)
    }
  ));

截图 截图来自 2018-09-25 13-23-02

我可以看到该值已被选中并且也在组件上设置,但我不知道为什么队列中有 1 个计时器以及如何解决它。

4

0 回答 0