Выбор конкретного TemplateRef из теста компонента Angular? - PullRequest
0 голосов
/ 28 марта 2019

У меня есть следующий компонент, имеющий ссылки для открытия модального окна, содержимое которого я могу изменить, передав ссылку на шаблон.

<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 из моего теста, но я не уверен, как это сделать.вот мой тест

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);
});

1 Ответ

2 голосов
/ 30 марта 2019

Извините за задержку, был занят в эти дни.Вы должны изменить свой 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();
  });
});

Наслаждайтесь !!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...