【问题标题】:Angular Testing: Get HTML Element inside child component that uses ng-contentAngular 测试:在使用 ng-content 的子组件中获取 HTML 元素
【发布时间】:2020-10-03 15:02:56
【问题描述】:

我在为使用ngb-accordion 显示其内容的组件编写单元测试时遇到问题。在这种情况下,手风琴仅用于样式目的,但我使用它来提供整个应用程序的设计一致性。

我能想到的最简单的模板来显示错误:

<ngb-accordion #acc="ngbAccordion" activeIds="sample">
  <ngb-panel id="sample">
    <ng-template ngbPanelContent>
      <p class="myClass">Some Text</p> <!-- I want to access this element -->
    </ng-template>
  </ngb-panel>
</ngb-accordion>

测试用例如下:

it('should find my element', () => {
    fixture = TestBed.createComponent(LoginComponent);

    component = fixture.componentInstance;
    fixture.detectChanges();
    const p = fixture.debugElement.query(By.css('.myClass')).nativeElement;
    p.id;
});

引发错误:

TypeError: Cannot read property 'nativeElement' of null

这是我的测试的beforeEach

beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ LoginComponent, NgbAccordion ],
      providers : [FormBuilder, ...]
    })
    .compileComponents();
  }));

(其中LoginComponent 是被测试的组件)。

我觉得和ng-template没有关系,和下面的html一样,元素找到正确:

<div *ngIf="false else always">Should not show</div>

<ng-template #always>
  <p class="myClass">Some Text</p>
</ng-template>

我不知道为什么它不适用于ngbAccordion,这可能是时间问题吗?因为我不是在嘲笑NgbAccordion 类(我也不想!),所以我希望它的内容能够正确呈现。是不是因为 html 可能是用“NgbAccordion”中的“ng-content”呈现的?如果是这样,我该怎么做才能访问我的元素?

非常感谢任何帮助。

【问题讨论】:

  • 你在组件中使用onPush变化检测机制吗?
  • 不,没什么。组件 (.ts) 可能为空。

标签: angular testing jasmine karma-runner ng-bootstrap


【解决方案1】:

当它在这样的外来元素中时,有时也会发生在我身上。

尝试直接访问nativeElement 或使用document.querySelector,而不是query

 const p = fixture.nativeElement.querySelector('.myClass');
 console.log(p); // see if it returns
 const p2 = document.querySelector('.myClass');
 console.log(p2); // see if it returns

如果这不起作用,请检查 nativeElement 并确保该元素存在;

const nativeElement = fixture.nativeElement;
console.log(nativeElement);

编辑:我不完全确定指令的类名是什么(可能是 NgBPanelContent),但请确保您在声明数组中包含它,以便 HTML 在看到该指令时知道如何绘制它。

【讨论】:

  • 不幸的是,没有。记录整个本机元素时,ngbAccordion 存在,但我的内容不存在。在测试环境之外查看页面时,当然会显示。
  • 也许您需要在声明中包含ngbPanelContent 指令。我看到你已经导入了它,但我认为它不知道如何绘制自己。
  • 就是这样!也许你可以编辑你的答案,然后我会接受它。
【解决方案2】:

我想你需要等待渲染;

// async added here
it('should find my element', async () => {
    fixture = TestBed.createComponent(LoginComponent);

    component = fixture.componentInstance;
    fixture.detectChanges();
    // and await rendering
    await fixture.whenRenderingDone();

    const p = fixture.debugElement.query(By.css('.myClass')).nativeElement;
    p.id;
});

【讨论】:

  • 我已经尝试使用 fakeAsynctick(500) 等待...也没有帮助。
  • 有一个stackblitz会很好。解决方案可能在于这个问题中揭示的代码 sn-ps 周围的代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-12
  • 2019-06-11
相关资源
最近更新 更多