angular - TypeError: No se pueden establecer propiedades de undefined (estableciendo 'object')
Tengo una función que al llamarla abre un modal de ngbModal, he importado todo lo necesario y también creado un mock de NgbModalRef, pero cuando realizo la prueba unitaria obtengo este error "TypeError: Cannot set properties of undefined (setting 'object')".
Intenté una solución en StackOverflow pero no funciona completamente, esta es la fuente: Escribiendo una prueba unitaria para el modal de ng-bootstrap (NgbModal) [Angular 6]
¿Cómo puedo arreglar ese error en mi prueba?
Mi función
remove = (report) => {
if (report.contents.length) {
const modalRef = this.modalService.open(ConfirmModalComponent,
{
scrollable: true,
windowClass: 'myCustomModalClass',
});
modalRef.componentInstance.object = 'Para borrar el informe "' + report.name + '" primero debe borrar los contenidos asociados.';
modalRef.componentInstance.button = "Aceptar";
modalRef.result.then((result) => {
}).catch(() => {
});
} else {
const modalRef = this.modalService.open(ConfirmModalComponent,
{
scrollable: true,
windowClass: 'myCustomModalClass',
});
modalRef.componentInstance.object = report.name;
modalRef.componentInstance.button = this.lang.get('delete');
modalRef.result.then((result) => {
if (result == 'accept') {
let idx = Object.keys(this.reports).filter(i => this.reports[i].id == report.id);
this.reports.splice(+idx[0], 1);
this.api.send('Reports', 'removeReport', { report: report })
}
}).catch(() => { });
}
}
Mi archivo de especificaciones:
import { NgbModule, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { Api, MenuService, FilterService, RoutingData } from 'is-common';
import { ReportsComponent } from './reports.component';
import { Router, RouterEvent, NavigationEnd } from '@angular/router';
import { ConfirmModalComponent } from '../../components/confirm-modal/confirm-modal.component';
export class MockNgbModalRef {
componentInstance: {
object: undefined,
button: undefined
}
result: Promise<any> = new Promise((resolve, reject) => resolve(true));
}
describe('ReportsComponent', () => {
let component: ReportsComponent;
let fixture: ComponentFixture<ReportsComponent>;
let api: Api;
let httpMock: HttpTestingController;
let menuService: MenuService;
let filterService: FilterService;
let routingData: RoutingData;
let routerTest: RouterTestingModule;
let ngbModal: NgbModal;
let mockModalRef: MockNgbModalRef = new MockNgbModalRef();
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
RouterTestingModule,
CookieModule.forRoot(),
NgbModule
],
declarations: [
ReportsComponent
],
providers: [
Api,
CookieService,
RoutingData,
MenuService,
FilterService,
{ provide: Router, useValue: routerMock },
{ provide: FilterSummaryPipe, useClass: FilterSummaryPipeMock }
],
schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA]
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ReportsComponent);
component = fixture.componentInstance;
ngbModal = TestBed.inject(NgbModal);
api = TestBed.inject(Api);
httpMock = TestBed.inject(HttpTestingController);
menuService = TestBed.inject(MenuService);
filterService = TestBed.inject(FilterService);
routingData = TestBed.inject(RoutingData);
});
describe('remove', () => {
it('Should remove the report', () => {
let report = { id:1, name: 'Prueba', date: "2021-09-23", contents: ['contenido de prueba'] }
let spy1 = spyOn(ngbModal, 'open').and.returnValue(MockNgbModalRef as any);
component.remove(report);
expect(spy1).toHaveBeenCalled();
expect(spy1).toHaveBeenCalledTimes(1);
expect(spy1).toHaveBeenCalledWith(ConfirmModalComponent, {scrollable: true, windowClass: 'myCustomModalClass'});
});
});
});
Respuesta #1
Dado que Angular utiliza TypeScript, necesitas mencionar el tipo de la variable que estás usando, así que dondequiera que estés usando una función flecha, especifica el tipo del objeto.
Por ejemplo: En tu archivo ts especifica el tipo para result también para filter
modalRef.result.then((result: any) => {
if (result == 'accept') {
let idx = Object.keys(this.reports).filter((i: any) => this.reports[i].id == report.id);
this.reports.splice(+idx[0], 1);
this.api.send('Reports', 'removeReport', { report: report })
}
}).catch(() => { });
