Как издеваться над @ViewChild MatTabGroup в шутку?

#javascript #angular #typescript #jestjs

#javascript #angular #машинописный текст #jestjs

Вопрос:

Я пытаюсь протестировать новый фрагмент кода, который я добавил в свой проект. Это позволяет пользователям выбирать вкладку на странице, и когда они обновляются, страница загружается на ту же вкладку. Для этого я использую localstorage.

Проблема, с которой я сталкиваюсь, заключается в тестах, в которых он не может установить selectedIndex of undefined .

В html на вкладке mat у меня есть обработчик событий ( selectedTabChange ):

 <mat-tab-group
  [selectedIndex]="selectedTab.value"
  (selectedIndexChange)="selectedTab.setValue($event)"
  (selectedTabChange)="handleMatTabChange($event)"
>
  <mat-tab label="Tab 1">
    <div *ngIf="selectedTab.value === 0"> ... </div>
  </mat-tab>

  <mat-tab label="Tab 2">
    <div *ngIf="selectedTab.value === 1"> ... </div>
  </mat-tab>

  <mat-tab label="Tab 3">
    <div *ngIf="selectedTab.value === 2"> ... </div>
  </mat-tab>

</mat-tab-group>
  

В компоненте у меня есть

 @ViewChild(MatTabGroup) tabGroup: MatTabGroup;


ngAfterViewInit() {
  const index = Number(localStorage.getItem('userTabLocation')) || 0;
  this.tabGroup.selectedIndex = index;
}

handleMatTabChange(event: MatTabChangeEvent) {
  localStorage.setItem('userTabLocation', String(event.index));
}
  

Тесты:

Проверка, определен ли ViewChild, но это undefined .

 it('Should have `ViewChild` variable defined', () => {
  expect(component.tabGroup).toBeDefined();
});
  

Также в некоторых других моих тестах я получаю:

 TypeError: Cannot set property 'selectedIndex' of undefined

   99 |   }
  100 | 
> 101 |   ngAfterViewInit() {
      |   ^
  102 |     const index = Number(localStorage.getItem('userTabLocation')) || 0;
  103 |     this.tabGroup.selectedIndex = index;
  

Вещи, которые я пробовал:

  1. Я прочитал эту действительно полезную статью https://blog.angularindepth.com/angular-unit-testing-viewchild-4525e0c7b756
  2. Поскольку мой дочерний элемент view является MatTabGroup, я понятия не имею, как его отключить, поэтому приведенная выше статья не очень помогла. Я пробовал это, но это нарушило еще больше тестов:

     component.tabGroup = TestBed.createComponent(MatTabGroup).componentInstance as MatTabGroup;
      
  3. Я добавил MatTabGroup в провайдеры подобным образом, что не помогло:

     TestBed.configureTestingModule({
          imports: [ ... ],
          declarations: [ ... ],
          providers: [
          {
             provide: MatTabGroup,
          }],
    }).compileComponents();
      
  4. Я добавил значения useValues в провайдеры с matTabGroup вот так, что также не помогло:

     TestBed.configureTestingModule({
          imports: [ ... ],
          declarations: [ ... ],
          providers: [
          {
             provide: MatTabGroup,
             useValues: {
                selectedIndex: 0,
             }
          }],
    }).compileComponents();
      
  5. Я добавил MatTabsModule в импорт, также не повезло:

     TestBed.configureTestingModule({
          imports: [ MatTabsModule ],
          declarations: [ ... ],
    }).compileComponents();
      

    Но это выдает следующую ошибку:

     Template parse errors:
    More than one component matched on this element.
    Make sure that only one component's selector can match a given element.
    Conflicting components: MatTab,MatTab ("
      

    (РЕДАКТИРОВАТЬ): это происходило потому, что я тоже импортировал MaterialModule .

Есть идеи? Действительно застрял на этом.

Заранее благодарю вас.

Комментарии:

1. Используя Jasmine и Karma, tabGroup не будет определен до тех пор, пока не будет выполнен хук ngAfterViewInit — я бы предположил, что вам нужно будет выполнить fixture.detectChanges() , а затем дождаться fixture.whenStable() возврата обещания, прежде чем оно будет установлено в тестовой среде. С помощью Jest вам нужно будет выполнить любой эквивалент в этой среде.