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
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?
CodePudding user response:
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');
});