[Fixed] How to click button element with Jasmine?

Issue

I need to know what happens inside a confirmation alert, but for that, I need to click on one of the alert buttons. I am not succeeding in doing this.

main.component.ts

async signOut() {

    const {
      ["modules.organizations.main.sign_out.confirmation.title"]: title,
      ["modules.organizations.main.sign_out.confirmation.message"]: message,
      ["modules.organizations.main.sign_out.confirmation.cancel"]: cancel,
      ["modules.organizations.main.sign_out.confirmation.ok"]: ok,
    } = await this.translate.get([
      "modules.organizations.main.sign_out.confirmation.title",
      "modules.organizations.main.sign_out.confirmation.message",
      "modules.organizations.main.sign_out.confirmation.cancel",
      "modules.organizations.main.sign_out.confirmation.ok"
    ]).pipe(first()).toPromise()

    //I need to know what happens inside here after click in button.
    this.alert.confirmation(title, message, cancel, ok).afterClosed()
    .subscribe(async value => {

      if(!value.ok) return
      const loading = this.alert.loading()
      
      try {
        await this.messaging.deleteToken()
        await this.firestore.devices(this.user.uid).doc(this.messaging.uuid()).update({ deleted: true, deletedAt: this.firestore.now })
        await this.auth.signOut()
        loading.close()
      } catch (error) {
        loading.close()
        await this.auth.signOut()
      }
    })
  }

main.component.spec.ts

fdescribe('MainComponent', () => {
  let component: MainComponent;
  let fixture: ComponentFixture<MainComponent>;
  let bottomSheetMock: jasmine.SpyObj<any>;
  let alertServiceMock: jasmine.SpyObj<any>;
  let dialogRefSpy: jasmine.SpyObj<any>;
  let functionsServiceMock: jasmine.SpyObj<any>;
  let messagingServiceMock: jasmine.SpyObj<any>;
  let routerMock: jasmine.SpyObj<any>;
  let router: Router;
  let el: DebugElement;
  
  bottomSheetMock = jasmine.createSpyObj('MatBottomSheet', ['open']);
  bottomSheetMock.open.and.returnValue('true');

  dialogRefSpy = jasmine.createSpy();
  dialogRefSpy.component = {title: 'error', message: 'error'};
  dialogRefSpy.afterClosed = () => of(true);

  const matDialogSpy = jasmine.createSpyObj('MatDialog', [
    'open',
    'close',
  ]);
  matDialogSpy.open.and.returnValue(dialogRefSpy);
  matDialogSpy.close.and.returnValue(dialogRefSpy);

  beforeEach(waitForAsync(() => {
    messagingServiceMock = jasmine.createSpyObj('MessagingService', [
      'requestPermission'
    ]);
    messagingServiceMock.requestPermission.and.callThrough();

    routerMock = jasmine.createSpyObj('Router',[
      'navigate'
    ]);
    routerMock.navigate.and.returnValue(true);

    alertServiceMock = jasmine.createSpyObj('AlertService',[
      'message',
      'error',
      'input',
      'password',
      'loading',
      'confirmation'
    ]);
    alertServiceMock.error.and.returnValue(matDialogSpy.open(AlertComponent, {
      data: { 
        type: 'error',
        title: 'error',
        error: 'description'
      },
      disableClose: true
    }));
    alertServiceMock.input.and.returnValue(matDialogSpy.open(AlertComponent, {
      data: { 
        type: 'input', 
        title: 'title', 
        description: 'description'
      },
      disableClose: true
    }));
    alertServiceMock.confirmation.and.returnValue(matDialogSpy.open(AlertComponent, {
      data: { 
        type: 'confirmation', 
        title: 'title', 
        message: 'message', 
        cancel: 'cancel', 
        ok: true
      },
      disableClose: true
    }))
    alertServiceMock.loading.and.returnValue(matDialogSpy);
    alertServiceMock.message.and.callThrough();

    TestBed.configureTestingModule({
      imports: [
        NoopAnimationsModule,
        AngularFireModule.initializeApp(environment.firebase),
        AngularFirestoreModule,
        OverlayModule,
        RouterTestingModule,
        MatDialogModule,
        MatChipsModule,
        TranslateModule.forRoot({
          loader: {
            provide: TranslateLoader,
            useClass: TranslateFakeLoader
          }
        })
      ],
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
      declarations: [
        MainComponent
      ],
      providers: [
        { provide: AlertService, useValue: alertServiceMock },
        { provide: MatDialog, useValue: matDialogSpy },
        { provide: MatBottomSheet, useValue: bottomSheetMock },
        { provide: Router, useValue: routerMock },
        { provide: MessagingService, useValue: messagingServiceMock },
        AuthService,
        TranslateService,
        UploadService,
        FormBuilder,
      ],
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(MainComponent);
    bottomSheetMock = TestBed.inject(MatBottomSheet);
    alertServiceMock = TestBed.inject(AlertService);
    messagingServiceMock = TestBed.inject(MessagingService);
    component = fixture.componentInstance;
    el = fixture.debugElement;
  });

  afterEach(() => {
    fixture.destroy();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should display confirmation alert', fakeAsync(async () => {
    await component.signOut();
    await fixture.whenStable();
    let buttonDebugElems: DebugElement[] = fixture.debugElement.queryAll(By.css('.mat-button'));
    console.log('elements =>');
    console.log(buttonDebugElems); // Here, I have 0 elements.
    
    expect(await alertServiceMock.confirmation).toHaveBeenCalled();
  }));
});

Obs: When the alert is generated, a button element is generated with it. But even searching the debugElement for a button, I can’t find anything.

Solution

I managed to solve the problem, the component was not being rendered, as it had *ngIf that returned false. If someone has the same problem, check if the component is being rendered with:

console.log(fixture.debugElement);

In the console you can view the elements of your html.

Leave a Reply

(*) Required, Your email will not be published