0

I am rying to assert that a mocked service method is called from my component. This is the relevant typescript code for the class:

export class EditProfileCardComponent {

  test = 'test'

  constructor(private messageHandlingService: MessageHandlingService) {}

  onFileSelected(event: any) {  
    const file: File = event.target.files[0];
    if(file.type != ValidFileTypes.JPG && file.type != ValidFileTypes.PNG) {
      this.test = "passed"; // this correctly sets the value to 'passed'
      this.displayInvalidFileTypeMessage();
    } else {
      // Some other logic...
    }
  }

 private displayInvalidFileTypeMessage() {
    this.messageHandlingService.displayMessage({
      message: "File selected must be JPEG or PNG file",
      action: SnackbarAction.Close,
      classType: SnackbarClassType.Error,
      duration: SnackbarDuration.Medium
    });
  }

}

This is the relevant html:

<p data-cy="test">{{test}}</p>
<input
   type="file"
   class="d-none"
   data-cy="file-input"
   accept=".png, .jpg"
   (change)="onFileSelected($event)"
   #fileUpload>

Here is my test:

 const messageHandlingService = {
    displayMessage: (snackBarItem: SnackBarItem) => {
      return null;
    }
  }

beforeEach(() => {
    cy.mount(EditProfileCardComponent, setupCypressConfig<EditProfileCardComponent>({
      providers: [
        {provide: MessageHandlingService, useValue: messageHandlingService}
      ]
    }));
  });

it("onFileSelected method should call display message method in messageHandlingService when invalid file type is selected", () => {
    cy.spy(messageHandlingService, 'displayMessage');
    cy.get(elementBindings.fileInput).selectFile('cypress/fixtures/incorrect file type.webp', { force: true });
    cy.wait(1000); 

    //1st assertion (THIS PASSES)
    cy.get('[data-cy="test"]').should('have.text', 'passed');

    //2nd assertion (THIS FAILS)
    expect(messageHandlingService.displayMessage).to.be.calledOnceWithExactly({
      message: "File selected must be JPEG or PNG file",
      action: SnackbarAction.Close,
      classType: SnackbarClassType.Error,
      duration: SnackbarDuration.Medium
    });
  });

The 2nd assertion in my test is failing with the message:

AssertionError: expected displayMessage to have been called exactly once with exact arguments Object{4}, but it was never called

I'm not sure where I am going wrong here as it seems like I have mocked the service correctly and also spied on the method correctly?

Here is the actual messageHandlingService for reference:

import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Subject, tap } from 'rxjs';
import { SnackBarItem } from '../models/snackbar-item';

@Injectable({
  providedIn: 'root'
})

export class MessageHandlingService {

  constructor(private snackbar: MatSnackBar) { }

  private displayNewMessage = new Subject<SnackBarItem>();

  newMessageReceived$ = this.displayNewMessage.pipe(
    tap(snackBarItem => this.displayMessage(snackBarItem))
  ).subscribe();

  onDisplayNewMessage(snackBarItem: SnackBarItem) {
    this.displayNewMessage.next(snackBarItem);
  }

  displayMessage(snackBarItem: SnackBarItem) {    
    this.snackbar.open(snackBarItem.message, snackBarItem.action, {
      panelClass: [snackBarItem.classType],
      duration: snackBarItem.duration,
      horizontalPosition: 'end'
    });
  }
}
Pablo52
  • 41
  • 6

1 Answers1

3

You should set up the spy before using it.

beforeEach(() => {
  cy.spy(messageHandlingService, 'displayMessage')
  cy.mount(EditProfileCardComponent, ...
});

It's looks like the mounting process gets a reference to the original displayMessage that is set up in the mock service messageHandlingService, before the mock can wrap the method.


You could probably also set the spy directly in the mock service, something like

const stub = Cypress.stub()
stub.withArgs({
  message: 'File selected must be JPEG or PNG file'   // tailor return to the args
}).returns(null)  

// or

stub.returns(null)                           // always returns null 

const messageHandlingService = {
  displayMessage: stub()
}
Briana
  • 204
  • 7