【问题标题】:Selecting a specific TemplateRef from Angular component test?从 Angular 组件测试中选择特定的 TemplateRef?
【发布时间】:2019-04-12 00:24:30
【问题描述】:

我有以下组件,其中包含打开模式的链接,我可以通过将模板引用传递到其中来改变其内容。

<a id="spec-tos" (click)="openModal($event, termsOfServiceModalTemplate)">Terms of Service</a>
<a id="spec-pp" (click)="openModal($event, privacyPolicyModalTemplate)">Privacy</a>

<ng-template #termsOfServiceModalTemplate>
  terms of service text goes here...
</ng-template>

<ng-template #privacyPolicyModalTemplate>
  privacy policy text goes here...
</ng-template>
export class FooterComponent {
  modalRef: undefined | BsModalRef;

  constructor(private modalService: BsModalService) {}

  openModal($event: Event, template: TemplateRef<NgTemplateOutlet>): void {
    $event.preventDefault();
    this.modalRef = this.modalService.show(template, {
      class: 'modal-dialog-scrollable'
    });
  }
}

如何测试链接是否打开了正确的模板?我需要能够从我的测试中选择 templateRef ID,但我不确定如何执行此操作。这是我的测试

it('should call the openModal() method when clicking on the privacy policy link', () => {
    spyOn(component, 'openModal');
    const link = debugEl.query(By.css('#spec-pp'));
    //This next line is wrong and does not work
    const tmpl = debugEl.query(By.directive(TemplateRef));
    link.triggerEventHandler('click', null);
    expect(component.openModal).toHaveBeenCalledWith(new MouseEvent('click'), tmpl);
});

我知道debugEl.query(By.directive(TemplateRef)) 不起作用...但这只是为了说明我想在这里做什么。如何从我正在测试的组件中选择特定模板?


编辑:下面@neo 的答案是解决方案,但我能够采用他的解决方案并将其打包成一个可重复使用的辅助函数

/**
 * Used for detecting an `<ng-template>` element reference that was passed to a function, typically for modals
 * We don't have access to much except the name of the template and a number that it maps to internally.
 * If we can return the number, then we've found the template by name, which is all we really want to do here
 * //https://stackoverflow.com/a/55432163/79677
 */
export const templateExists = (template: TemplateRef<NgTemplateOutlet>, templateName: string): boolean => {
    // tslint:disable-next-line:no-any  --  There is no other way to get this object, it doesn't exist in the typedefs!
    const refs = (template as any)._def.references as {[templateName: string]: number};
    //If we have a number, then we've found the template by name
    return !isNaN(refs[templateName]);
};

像这样使用它:

it('should call the openModal() method when clicking on the privacy policy link', () => {
    const modalSpy = spyOn(component, 'openModal');
    const link = debugEl.query(By.css('.footer-nav .spec-privacy'));
    link.triggerEventHandler('click', null);
    expect(component.openModal).toHaveBeenCalled();
    expect(templateExists(modalSpy.calls.mostRecent().args[1], 'privacyPolicyModalTemplate')).toEqual(true);
});

【问题讨论】:

  • 你能提供BsModalRefBsModalService的课程吗,我想我可以帮助你。
  • 这些来自ngx-bootstrap valor-software.com/ngx-bootstrap/#/modals - 我不拥有它们
  • 我已经在下面添加了答案,你可以检查一下吗?

标签: angular angular-template angular-test


【解决方案1】:

抱歉,这几天很忙,耽搁了。您应该如下修改您的spec.ts

import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { FooterComponent } from './footer.component';
import { BrowserModule, By } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatButtonModule } from '@angular/material';
import { ModalModule } from 'ngx-bootstrap';

describe('FooterComponent ', () => {
  let component: FooterComponent;
  let fixture: ComponentFixture<FooterComponent>;
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        FooterComponent
      ],
      imports: [
        // your imports here
        ModalModule.forRoot()
      ]
    }).compileComponents();
  }));

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

  it('should create the app', () => {
    expect(component).toBeTruthy();
  });


  it('should call the openModal() method when clicking on the links', () => {
    const obj = spyOn(component, 'openModal');
    let link = fixture.debugElement.query(By.css('#spec-tos'));
    link.triggerEventHandler('click', null);
    expect(component.openModal).toHaveBeenCalled();
    expect(obj.calls.mostRecent().args[1]._def.references.termsOfServiceModalTemplate).toBeDefined();

    link = fixture.debugElement.query(By.css('#spec-pp'));
    link.triggerEventHandler('click', null);
    expect(component.openModal).toHaveBeenCalledTimes(2);
    expect(obj.calls.mostRecent().args[1]._def.references.privacyPolicyModalTemplate).toBeDefined();
  });
});

享受!!

【讨论】:

  • 非常酷,谢谢!可惜这些东西不是强类型的,但至少我可以让它们可测试
猜你喜欢
  • 2019-03-25
  • 2018-05-14
  • 2019-11-21
  • 1970-01-01
  • 2017-04-03
  • 1970-01-01
  • 2012-11-25
  • 2020-12-13
  • 2019-03-26
相关资源
最近更新 更多