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'
});
}
}