JD Carr
JD Carr

Reputation: 239

How can I test an event emitter inside an afterClosed mat dialog subscription?

I am trying to test an event emitter inside an afterClosed mat-dialog subscription and I'm really confused about how to do so.

My dialog function:

public openDialog(type: string): void {
  const newDialog = this.dialog.open(NewModalComponent, {
    width: '580px',
    data: {
      type: type,
      data: this.oldData
    }
  })

  newDialog.afterClosed().subscribe(result => {
    if(result) {
      this.updateState.emit({
        newData: result,
        oldData: this.oldData,
        type: type
      })
    }
  })
}

And here is my test:

// I'm not sure what to do or how to test if data will be emitted
it('should have data if apply was clicked', () => {
  spyOn(component.dialog, 'open').and.returnValue({afterClosed: () => of(true)})
  // something happens here?
})

Here is my mockDialog setup:

class MatDialogMock {
  open() {
    return {
      afterClosed: () => of({ data: 'returned data' })
    }
  }
}

describe('ButtonsComponent', () => {
  let component: ButtonsComponent
  let fixture: ComponentFixture<ButtonsComponent>
  let dialog: MatDialogMock

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        MaterialModule,
        NoopAnimationsModule
      ],
      declarations: [ 
        ButtonsComponent,
      ],
      providers: [
        {
          provide: MatDialog, useClass: MatDialogMock
        }
      ]
    })
    .compileComponents()
  }))

Has anyone been successful testing the results from the afterClosed subscription?

My tries: This test fails with: : Expected a spy, but got Function.

it('should have data if apply was clicked', () => {
  spyOn(component.dialog, 'open').and.returnValue({afterClosed: () => of(true)})
  component.openDialog('Pending')
  expect(component.updateState.emit).toHaveBeenCalled()
})

This test fails with: test fails with Expected spy emit to have been called.

it('should have data if apply was clicked', () => {
  spyOn(component.dialog, 'open').and.returnValue({afterClosed: () => of(true)})
  component.openDialog('Pending')
  spyOn(component.updateState, 'emit')
  expect(component.updateState.emit).toHaveBeenCalled()
})

Upvotes: 2

Views: 2161

Answers (2)

JD Carr
JD Carr

Reputation: 239

I got this to work with the following:

beforeEach(() => {
  fixture = TestBed.createComponent(ButtonsComponent)
  dialog = TestBed.get(MatDialog)
  component = fixture.componentInstance

  spyOn(component.updateState, 'emit') // need to have the emit spy before the test
  fixture.detectChanges()
})

it('should have data if apply was clicked', () => {
  spyOn(component.dialog, 'open').and.returnValue({afterClosed: () => of(true)})
  component.openDialog('Test')
  expect(component.updateState.emit).toHaveBeenCalled()
})

Upvotes: 1

Morphyish
Morphyish

Reputation: 4062

The easiest to do this, in my opinion, would be to encapsulate your afterClosed callback in a function, and unit test it independently by calling it directly.

If you want to make sure everything is happening properly when you are closing the dialog, you should test this in End to End test with a testing suit such as cypress.

Upvotes: 1

Related Questions