#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(),
});
Мне не удалось протестировать приведенный выше код, но я надеюсь, что он поможет понять идею и с небольшими корректировками он будет работать.