1

I have a unit test in angular. I need to test the functionality of save button. So when user clicks on save button a popup appears with save and cancel . SO i want the save to be chosen automatically and execute the next line of codes.

beforeEach(async () => {

    fixture = TestBed.createComponent(component);
    component = fixture.componentInstance;
    fixture.detectChanges();
    component.isPrivate = true;
    component.qtsval= 7.0;
    component.changeval= "";
    await component.save();
    //let ConfirmationDialogService = fixture.debugElement.injector.get(ConfirmationDialogComponent);
    spyOn(window,'confirm').and.returnValue(true);
    var displayValuationChangeDriverWarning = component.displayValuationChangeDriverWarning;
    expect(displayValuationChangeDriverWarning).toBeTruthy();
    component.isPrivate = true;
    component.qtsval= 4.0;
  });

I used " spyOn(window,'confirm').and.returnValue(true);" but it doesnt help. Please suggest me how to solve this

I have the popup window like this :

this.confirmationDialogService
      .confirm(
        this._messageService.areYouSure,
        this._messageService.wouldYouSave,
        this._messageService.save,
        this._messageService.cancel,
        true,
        false
      )
      .then(async confirmed => {});
ashish
  • 282
  • 8
  • 27

1 Answers1

0

Ok, I have something that's working and ready for you to take a look at, essentially the approach is to separate presentation testing from business logic, I tested the contracts between components/providers to ensure the correct methods are being called internally.

This is repeated across all relevant components, this is testing solely the logic behind the buttons.

In e2e, I've tested to ensure the modal displays, and the buttons are present, admittedly you'd also want to ensure the modal disappears and the buttons also disappear and are no longer enabled, but I'm sure you're not looking for a complete example here.

This is a separation of concerns, keeping logic away from your UI. As I mentioned in my above comment, I'd personally opt to use unit testing for only my logic, and e2e testing on the UI components (ensuring that if you hit a button, it'll retrieve from a service or whatever your intention may be).

Anyway, enough talk, more code. I'll post a few examples for anyone who finds themselves in a similar position to OP. Github link at the bottom.

Unit testing would look similar to:

  it('.reject() should call activeModal with false', async () => {
    spyOn(activeModal, 'close').and.returnValue(null);

    expect(component.decline()).toBeUndefined();

    expect(activeModal.close).toHaveBeenCalledTimes(1);
    expect(activeModal.close).toHaveBeenCalledWith(false);
  });

And:

  it('should return the correct result of a Modal (object is correct, calls internal modal)', async () => {
    const mock = {
      componentInstance: {
        title: 'Are you sure?',
        message: 'Are you actually sure though?',
        btnOkText: 'OK',
        btnCancelText: 'Cancel',
      },
      result: true,
    };

    spyOn(modal, 'open').and.returnValue(mock as any);

    const result = await service.confirm(
      mock.componentInstance.title,
      mock.componentInstance.message
    );

    expect(result).toBe(mock.result);

    expect(modal.open).toHaveBeenCalledTimes(1);
    expect(modal.open).toHaveBeenCalledWith(ModalComponent, { size: 'sm' });
  });

Whereas, my e2e testing would look more like:

  it('should have an Open button on the home page, the button should open a modal with an OK option (returning TRUE)', async () => {
    page.navigateTo();

    const button = await page.getButton();
    expect(button.getText()).toBe('Open');
    await button.click();

    const modal = await page.getConfirmationModal();
    expect(await modal.isEnabled()).toBeTruthy();

    const acceptBtn = await page.getAcceptButton();

    expect(await acceptBtn.isDisplayed()).toBeTruthy();
    expect(await acceptBtn.isEnabled()).toBeTruthy();
    expect(await acceptBtn.getText()).toBe('OK');
    await acceptBtn.click();
  });

It's not the most elegant testing (if I took more time it'd test more areas, but I'm sure you can get that bit).

I'll also say, this way isn't strictly right, technology in general isn't really about right and wrong, however, I'm not entirely sure how analysing DOM events would work in unit testing.

Although testing the logic is entirely possible (sort of the purpose (IMO)).

https://github.com/Isolated-/angular-dialog-example-stack-overflow

I hope this in someway helped to resolve your frustration, if I've got the wrong idea let me know and I'll correct it!

Isolated
  • 2,167
  • 14
  • 14
  • This is not working for me. I think the code you have written in stackblitz is my actual scenario. Can you try to give me the solution there itself? – ashish May 09 '20 at 18:48
  • I can't find anyway of sending commands to stackblitz, so I wouldn't be able to reproduce it there I'm afraid, however if you can give me an idea of what went wrong I can certainly fix that. – Isolated May 09 '20 at 19:13
  • 1
    can you give me the full specs.ts class code of the above written code by you. Basically i want the then to be executed so that means when user gets a confirm dialog it should automatically select the true one and continue with the then part – ashish May 09 '20 at 19:29