'Unhandled Promise rejection: alert.present is not a function

When I call my delete method I'm net with an error: Unhandled Promise rejection: alert.present is not a function.

I'd like to test the button handlers but I am being blocked by this error.

Component

  async delete() {
    const alert = await this.alertCtrl.create({
      header: 'Confirmation',
      message: 'Somemessage',
      buttons: [
        {
          text: 'Cancel',
          role: 'cancel',
          cssClass: 'secondary',
          handler: () => {
            console.log('cancel');
          },
        },
        {
          text: 'Delete',
          handler: () => {
            console.log('Delete');
          },
        },
      ],
    });
    await alert.present();
  }

Spec

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;

  @Component({ selector: 'my-component', template: '' })

  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        declarations: [MyComponent],
        providers: [],
      }).compileComponents();
    })
  );

  beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });
   
  it('should call button handler', () => {
    // Unhandled Promise rejection: alert.present is not a function
    component.delete();
  });
});


Solution 1:[1]

The Spec is not implemented correctly. You do not have to set this line:

@Component({ selector: 'my-component', template: '' })

If you have nested components in MyComponent component, you can refer to this https://angular.io/guide/testing-components-scenarios#nested-component-tests

In the component code you posted, I suppose that alertCtrl is a service, if so, there should be a spy that must be added in the TestBed providers with a mock of its create method.

Here is an example of Spec implentation:

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;
  let alertCtrlSpy: jasmine.SpyObj<AlertCtrlService>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [MyComponent],
      providers: [
        {
          provide: AlertCtrlService,
          useValue: jasmine.createSpyObj('AlertCtrlService', ['create'])
        }
      ],
    }).compileComponents();
    alertCtrlSpy = TestBed.inject(AlertCtrlService) as jasmine.SpyObj<AlertCtrlService>;
  });

  beforeEach(() => {
    alertCtrlSpy.create.and.returnValue(myAlert); // <------- Should be a fake alert used for test
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });
   
  it('should call button handler', () => {
    // Unhandled Promise rejection: alert.present is not a function
    component.delete();
  });
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 KSoze