单元测试中未显示 PrimeNG 菜单栏启动指令

PrimeNG menubar start directive not displayed in unit test

我正在我的包含 PrimeNG 菜单栏的组件上编写 Jasmine 测试。我正在使用 start 模板指令,如下所示:

<p-menubar id='menubar' [model]='items'>
  <ng-template pTemplate='start'>
    <span id='menubarTitle' class='nsg-primary-color nsg-bold'>{{ title }}:</span>
  </ng-template>
</p-menubar>

我正在尝试测试 start 模板指令是否存在。为了方便起见,我在 span 标签中添加了一个 id 并尝试获取 span 元素:

it('should render start menubar title ...', () => {
  // given / when
  const expectedMenuTitle = 'Net Incident:';
  const menubarTitle: HTMLSpanElement = fixture.debugElement.query(
    By.css( '#menubarTitle' )).nativeElement;
  // then
  expect( menubarTitle.innerText ).toEqual( expectedMenuTitle );
});

但我收到以下 Jasmine 错误消息:

MenuComponent > should render start menubar title ...
 TypeError: Cannot read property 'nativeElement' of null

在玩弄 Jasmine 渲染 (id='menubar') 时,似乎 div.p-menubar-start.ng-star-inserted元素不显示。在我的应用程序中,显示了 start 文本。当我查看 GitHub 上的源代码时,PrimeFaces 似乎没有在单元测试中对此进行测试。怎么办?

缩写规格如下:

// File: menu.component.spec.ts
import { ComponentFixture, TestBed, waitForAsync, fakeAsync, tick } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { By } from '@angular/platform-browser';
//
import { Menubar, MenubarModule } from 'primeng/menubar';
//
import { MenuComponent } from './menu.component';
//
describe('MenuComponent', () => {
  let component: MenuComponent;
  let fixture: ComponentFixture<MenuComponent>;
  //
  beforeEach( waitForAsync( () => {
    TestBed.configureTestingModule({
      imports: [
        MenubarModule,
        RouterTestingModule
      ],
      declarations: [
        Menubar,
        MenuComponent
      ]
    } );
    TestBed.compileComponents( );
  }));
  //
  beforeEach( fakeAsync( () => {
    fixture = TestBed.createComponent(MenuComponent);
    component = fixture.componentInstance;
    tick( 1000 );
    fixture.detectChanges();
  }) );
  // two tests removed ...
  it('should render start menubar title ...', () => {
    // given / when
    const expectedMenuTitle = 'Net Incident:';
    const menubarTitle: HTMLSpanElement = fixture.debugElement.query(
      By.css( '#menubarTitle' )).nativeElement;
    // then
    expect( menubarTitle.innerText ).toEqual( expectedMenuTitle );
  });
  //
});

By.CSS可能是CSSclass的名字,你可以试试By.ID

我认为您需要将 MenuBarModule 放入 TestBed.configureTestingModule({})imports 数组中,以便您的组件知道如何绘制它。

像这样:

import {MenubarModule} from 'primeng/menubar';

TestBed.configureTestingModule({
    imports: [MenubarModule,], // can put your other stuff here too
    declaratations: [],
    providers: [],
    schemas: [],    
  }).compileComponents();

编辑==== 也许您遗漏了 fixture.detectChanges() 或某些 asynchronous 必须发生才能显示。有时fixture.debugElement查询不到,可以试试documentfixture.nativeElement。我以前用Ag-Grid的时候就遇到过这种情况。

尝试:

it('should render start menubar title ...', async (done) => {
  // given / when
  const expectedMenuTitle = 'Net Incident:';
  fixture.detectChanges();
  await fixture.whenStable();
  setTimeout(() => {
    console.log(fixture.nativeElement); // ensure the nativeElement has 
    // the element you're looking for.
    const element = document.querySelector('#menubarTitle');
    console.log(element); // see if it's queryable by the document element
    const element2 = fixture.nativeElement.querySelector('#menubarTitle');
    console.log(element2); // see if it's queryable by the fixture element
    const menubarTitle: HTMLSpanElement = fixture.debugElement.query(
    By.css( '#menubarTitle' )).nativeElement;
     // then
    expect( menubarTitle.innerText ).toEqual( expectedMenuTitle );
    done();
  }, 500);
});

我必须添加以下导入:

  import { SharedModule } from 'primeng/api';
  ...
      imports: [
        MenubarModule,
        SharedModule,
        RouterTestingModule
      ],

更完整的规范如下:

// File: menu.component.spec.ts
import { ComponentFixture, TestBed, waitForAsync, fakeAsync, tick } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { By } from '@angular/platform-browser';
//
import { SharedModule } from 'primeng/api';
import { Menubar, MenubarModule } from 'primeng/menubar';
//
import { MenuComponent } from './menu.component';
//
describe('MenuComponent', () => {
  let component: MenuComponent;
  let fixture: ComponentFixture<MenuComponent>;
  //
  beforeEach( waitForAsync( () => {
    TestBed.configureTestingModule({
      imports: [
        MenubarModule,
        SharedModule,
        RouterTestingModule
      ],
      declarations: [
        Menubar,
        MenuComponent
      ]
    } );
    TestBed.compileComponents( );
  }));
  //
  beforeEach( fakeAsync( () => {
    fixture = TestBed.createComponent(MenuComponent);
    component = fixture.componentInstance;
    tick( 1000 );
    fixture.detectChanges();
    fixture.whenStable();
  }) );
  // ... two tests removed
  it('should render start menubar title ...', () => {
    // given / when
    const expectedMenuTitle = 'Net Incidents:';
    const menubarTitle: HTMLSpanElement = fixture.debugElement.query(
      By.css( '#menubarTitle' )).nativeElement;
    // then
    expect( menubarTitle.innerText ).toEqual( expectedMenuTitle );
  });
  //
});