Не удается получить доступ к textContent mat-dialog-title для привязки данных модульного теста - PullRequest
0 голосов
/ 07 января 2019

Я пытаюсь проверить привязку данных заголовка диалога для всплывающего диалогового окна углового материала. Однако, даже если элемент, который я запрашиваю (см. Код ниже), возвращается правильно, я не могу получить программный доступ к тексту, содержащемуся в элементе.

user.ts

export class User {
    id: number;
    firstName: string;
    lastName: string;
    eMail: string;
    mobile: string;
}

пользователем dialog.component.html

<h1 mat-dialog-title>{{data.dialogTitle}}</h1>

пользовательский dialog.component.ts

import { Component, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { User } from 'src/core/models/user';

@Component({
  selector: 'app-user-dialog',
  templateUrl: './user-dialog.component.html',
  styleUrls: ['./user-dialog.component.scss']
})
export class UserDialogComponent {

  constructor(
    public dialogRef: MatDialogRef<UserDialogComponent>,
    @Inject(MAT_DIALOG_DATA) public data: DialogData) {}

  onNoClick(): void {
    this.dialogRef.close();
  }
}

export interface DialogData {
  user: User;
  dialogTitle: string;
}

пользовательский dialog.component.specs.ts

import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { UserDialogComponent } from './user-dialog.component';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from '@angular/forms';
import { MatDialogModule, MatDialogRef } from '@angular/material';
import { MatTableModule, MatFormFieldModule, MatDialog } from '@angular/material';
import { MatInputModule, MatButtonModule, MatTooltipModule, MatIconModule } from '@angular/material';
import { MAT_DIALOG_DATA } from '@angular/material';
import { User } from 'src/core/models/user';
import { NgModule } from '@angular/core';
import { OverlayContainer } from '@angular/cdk/overlay';

const TEST_DIRECTIVES = [
  UserDialogComponent
];

@NgModule({
  imports: [FormsModule, MatFormFieldModule, MatInputModule, MatDialogModule, NoopAnimationsModule],
  exports: TEST_DIRECTIVES,
  declarations: TEST_DIRECTIVES,
  entryComponents: [
    UserDialogComponent
  ],
  providers: [
    { provide: MatDialogRef, useValue: {} },
    { provide: MAT_DIALOG_DATA, useValue: { user: new User(), dialogTitle: 'no title' } }
  ]
})
class UserDialogComponentTestModule {
  constructor(public dialog: MatDialog) { }
}


describe('UserDialogComponent', () => {
  let component: UserDialogComponent;
  let fixture: ComponentFixture<UserDialogComponent>;
  let dialog: MatDialog;
  let overlayContainerElement: HTMLElement;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
      ],
      imports: [
        BrowserModule,
        MatDialogModule,
        MatTableModule,
        MatButtonModule,
        MatTooltipModule,
        MatIconModule,
        UserDialogComponentTestModule
      ],
      providers: [
        {
          provide: OverlayContainer, useFactory: () => {
            overlayContainerElement = document.createElement('div');
            return { getContainerElement: () => overlayContainerElement };
          }
        }
        // // workaround: why I can't inject MatDialogRef in the unit test?
        // {provide: MatDialogRef, useValue: {}},
        // {provide: MAT_DIALOG_DATA, useValue: {user: new User(), dialogTitle: 'no title'}}
      ]
    })
    .compileComponents();

    dialog = TestBed.get(MatDialog);
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(UserDialogComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    console.log('UserDialogComponent should create');
    expect(component).toBeTruthy();
  });

  it('should display user passed into it', () => {
    console.log('UserDialogComponent should display user passed into it');
    const dialogTitle = 'Test display';
    const user: User = new User();

    const dialogRef = dialog.open(UserDialogComponent, {
      data: { user: user, dialogTitle: dialogTitle }
    });

    console.log('overlayContainerElement', overlayContainerElement);  // <div>...</div>

    // check dialog title
    const title = overlayContainerElement.querySelector('h1');
    console.log('title', title);
      // <h1 _ngcontent-c11="" class="mat-dialog-title" mat-dialog-title="" id="mat-dialog-title-2">Test display</h1>
    console.log('title.tagName', title.tagName);
      // H1
    console.log('title.textContent', title.textContent);
      // empty - why?
    console.log('title.#childNodes', title.childNodes.length);
      // 1
    console.log('title.childNode[0]', title.childNodes[0]);
      // "Test display"
    console.log('title.childNode[0].textContent', title.childNodes[0].textContent);
      // empty - why

    expect(title.childNodes.length).toBe(1);
    // expect(title.childNodes[0].textContent).toBe(dialogTitle); --> fails?
    // expect(title.textContent).toContain(dialogTitle); --> fails?
  });

1 Ответ

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

Открытие диалога не является синхронной задачей. Например, оберните свою логику тестирования в afterOpened(), которая сообщит вам, как только диалог будет готов. Здесь - это стек, где проходит ваш тест.

Это может выглядеть так:

it('should display user passed into it', (done) => {
  console.log('UserDialogComponent should display user passed into it');
  const dialogTitle = 'Test display';
  const user: User = new User();

  const dialogRef = dialog.open(UserDialogComponent, {
    data: { user: user, dialogTitle: dialogTitle }
  });

  dialogRef.afterOpen().subscribe(() => {
    console.log(document.querySelector('div'));
    console.log('overlayContainerElement', overlayContainerElement);

    // check dialog title
    const title = overlayContainerElement.querySelector('h1');
    console.log('title', title);
    console.log('title.tagName', title.tagName);
    console.log('title.textContent', title.textContent);
    expect(title.textContent).toBe('Test display');

    console.log('title.#childNodes', title.childNodes.length);
    console.log('title.childNode[0]', title.childNodes[0]);
    console.log('title.childNode[0].textContent', title.childNodes[0].textContent);

    done();
  });
});

Не забудьте добавить (done) => и затем вызвать done(), поскольку ваш тест теперь выполняется асинхронно.

...