I'm trying to create a simple Cypress test that tests whether a service method was called. Here is my test setup:
const accountService = {
logout: () => {
return null;
}
}
beforeEach(() => {
cy.mount(ToolbarComponent, {
imports: [
MatDialogModule,
MatMenuModule,
MatToolbarModule,
MatButtonModule,
BrowserAnimationsModule,
MatIconModule
],
declarations: [ToolbarComponent],
providers: [{provide: AccountService, useValue: accountService}]
});
});
describe('logout method', () => {
it('should call the account service logout method', () => {
cy.spy(accountService, 'logout').as('accountService-logout-method');
cy.get(elementBindings.userMenuButton).click();
cy.wait(1000);
cy.get(elementBindings.logoutButton).should('be.visible'); // THIS PASSES
cy.get(elementBindings.logoutButton).click();
expect(accountService.logout).to.be.called;
});
});
This is the relevant html:
<button
data-cy="open-user-menu-button"
mat-icon-button
class="example-icon favorite-icon"
aria-label="Example icon-button with heart icon"
[matMenuTriggerFor]="menu">
<mat-icon>person</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item>Edit Profile</button>
<button data-cy='logout-button' *ngIf="loggedOnUser$ | async" mat-menu-item (click)="logout()">Logout</button>
</mat-menu>
This is the logout()
method in the component.ts file:
logout() {
this.accountService.logout();
}
The last expect statement: expect(accountService.logout).to.be.called;
is failing and I cannot understand why? The expect()
statement to verify the button is visible passes and I can physically see the button is there in Cypress before the click()
method is called on it.
Any ideas why this might be happening?
So the main reason you're likely having an issue is because Cypress is asynchronous.
So using the expect()
outside of a then()
or should()
callback won't work since you have to wait for the Cypress commands to complete.
I see you already have an alias on your spy, so to assert a spy:
// Instead of this
expect(accountService.logout).to.be.called;
// Get the alias, then use should() to assert
cy.get('@accountService-logout-method').should('have.been.called');
// or
cy.get('@accountService-logout-method').should((spy) => {
expect(spy).to.be.called;
});
Your entire test would look something like this:
// Entire test
it('should call the account service logout method', () => {
cy.spy(accountService, 'logout').as('accountService-logout-method');
cy.get(elementBindings.userMenuButton).click();
cy.wait(1000);
cy.get(elementBindings.logoutButton).should('be.visible'); // THIS PASSES
cy.get(elementBindings.logoutButton).click();
cy.get('@accountService-logout-method').should('have.been.called');
});