Насмешливый модальный.контент.OnClose.подписка в BsModalRef

#angular #jasmine #karma-jasmine #ngx-bootstrap

Вопрос:

У меня есть универсальный компонент ModalConfirm (ngx-bootstrap), который выглядит следующим образом:

 export class ModalConfirmComponent {
  public active = false;
  public body: string | undefined | null;
  public title: string | undefined | null;
  public onClose = new Subject<boolean>();

  public constructor(private bsModalRef: BsModalRef) {}

  public showConfirmationModal(title: string, body: string): void {
    this.title = title;
    this.body = body;
    this.active = true;
  }

  public onConfirm(): void {
    this.active = false;
    this.onClose.next(true);
    this.bsModalRef.hide();
  }

  public onCancel(): void {
    this.active = false;
    this.onClose.next(false);
    this.bsModalRef.hide();
  }

  public hideConfirmationModal(): void {
    this.active = false;
    this.onClose.next(undefined);
    this.bsModalRef.hide();
  }
}
 

Он вызывается из службы следующим образом:

   addElementWithConfirmation(
    course: ICourse | undefined | null,
    courseContents: ICourseContent[] | undefined | null,
    selectedCourseContentUid: string | undefined | null,
    selectedCourseContentElementUid: string,
    selectedCourseModule: number | undefined | null,
    showAddElementMenu: boolean,
    courseContentElementMethod: CourseContentElementsMap,
    confirmElementReplacementModalBody: string
  ): void {
    if (
      course amp;amp;
      courseContents amp;amp;
      selectedCourseContentUid amp;amp;
      !UtilService.isNullOrUndefined(selectedCourseModule)
    ) {
      if (
        this.canCourseContentElementBeAdded(
          courseContentElementMethod,
          courseContents,
          selectedCourseContentUid
        )
      ) {
        const modal = this.modalService.show(ModalConfirmComponent);
        if (modal amp;amp; modal.content) {
          modal.content.showConfirmationModal(
            CONFIRM_MODAL_TITLE,
            confirmElementReplacementModalBody
          );
          modal.content.onClose.subscribe((result) => {
            if (result) {
              this.hideAddElementMenu(showAddElementMenu);
              courseContents = ADD_COURSE_CONTENT_ELEMENT_MAP[courseContentElementMethod](
                (courseContents as unknown) as ICourseContent[],
                selectedCourseContentElementUid,
                selectedCourseContentUid
              );
            } else {
              this.hideAddElementMenu(showAddElementMenu);
            }
          });
      }
    }
  }
 

Проблема, с которой я сейчас сталкиваюсь, связана с тестированием, все, что в modal.content.onClose.subscribe((result) => { настоящее время недоступно, — это код. Как мне это исправить? Мой тест выглядит следующим образом:

   describe('addElementWithConfirmation()', () => {
    it('should add element', () => {
      spyOn(service, 'canCourseContentElementBeAdded').and.callThrough();
      let newCourseContents: ICourseContent[] = JSON.parse(JSON.stringify(courseContents));
      service.addElementWithConfirmation(
        course,
        newCourseContents,
        newCourseContents[0].uid,
        `${CourseContentElementType.AUDIO}-${UtilService.generateRandomString(10)}`,
        0,
        true,
        CourseContentElementsMap.ADD_COURSE_CONTENT_ELEMENT_AUDIO,
        'test'
      );
      expect(service.canCourseContentElementBeAdded).toHaveBeenCalled();
    });
 

Я знаю, что лучше всего было бы издеваться над BsModalRef следующим образом, но я не уверен, как издеваться над возвращением modal.content.onClose.subscribe ? Например, вот пример, в котором содержимое равно нулю:

       spyOn(mockModalService, 'show').and.returnValue({
        id: 1,
        content: null,
        hide: () => {},
        setClass: () => {},
        onHide: new EventEmitter(),
        onHidden: new EventEmitter(),
      });
 

Каков был бы наилучший способ решения этой проблемы?

Ответ №1:

Чтобы иметь покрытие внутри modal.content.onClose.subscribe((result) => { части кода, я бы создал функцию-шпиона для onClose функции и вернул бы поддельное наблюдаемое. Сложность в том, что this.modalService.show , возвращая instace, этот экземпляр должен быть осмеян и должен возвращать осмеянный объект, содержащий шпиона для content.onClose .

Из этого следует, что необходимо нечто подобное:

   const onCloseSpy = jasmine.createSpy().and.returnValue(of({})); // Here the rxjs of operator needes to return the onClose result object istead of the empty {} object. Please change add the object based on your needs.
  const contentMock = {onClose: onCloseSpy};
  spyOn(mockModalService, 'show').and.returnValue({
    id: 1,
    content: contentMock,
    hide: () => {},
    setClass: () => {},
    onHide: new EventEmitter(),
    onHidden: new EventEmitter(),
  });
 

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