I am learning the basics of testing and I am using a chat I developed with Angular and Firebase.
I have a method to authenticate the user based on different providers. The provider´s name will be passed as argument. It will call another method on a service which will make the logic.
authentication() will be called when we push a button, that way the button to log with google will call authentication('google')
, the button to log wih facebook will be authentication ('facebook')
and so on.
login.component.ts
authenticate(provider:String){
this._chat.login(provider).then(()=>{
}).catch((error)=>{
console.log ("something went wrong with the authenticate method", error);
});
}
To do the test, I created an spy on that method and I am trying to recreate the different clicks. When I make something like
spyOn(component, 'authenticate').withArgs('google');
buttonElement.click();
expect(component.authenticate).toHaveBeenCalledWith('google');
But when I make another test with a different parameter:
spyOn(component, 'authenticate').withArgs('facebook');
buttonElement.click();
expect(component.authenticate).toHaveBeenCalledWith('facebook');
It throws an error, since it seems it calls the parameter it called the first time:
I have been investigating and tried to use the solution proposed here but it doesn´t work.
As you can see in the following code, I am resetting the spy inside the beforeEach()
.
How can I use different parameters each time I use the spy and make it work? What else could be I doing wrong?
This is the whole spec code.
login.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginComponent } from './login.component';
import { ChatService } from '../../services/chat-service/chat.service';
import { DebugElement } from '@angular/core';
import { AngularFireModule } from '@angular/fire/compat';
import { environment } from 'src/environments/environment';
import { RouterTestingModule } from '@angular/router/testing';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
let debugElement: DebugElement;
let _chat:ChatService;
let buttonElement:HTMLButtonElement;
let spy1:any;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ LoginComponent ],
imports:[RouterTestingModule,
AngularFireModule.initializeApp(environment.firebase),
],
providers: [ChatService]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
debugElement = fixture.debugElement;
_chat=debugElement.injector.get(ChatService);
component = fixture.componentInstance;
buttonElement = fixture.debugElement.nativeElement.querySelector('.button-login');
spy1=spyOn(component, 'authenticate');
spy1.calls.reset();
});
it('should click google button and call authenticate method with google', () => {
spy1.withArgs('google');
buttonElement.click();
expect(component.authenticate).toHaveBeenCalledWith('google');
});
it('should click facebook button and call authenticate method with facebook', () => {
spy1.withArgs("facebook");
buttonElement.click();
expect(component.authenticate).toHaveBeenCalledWith('facebook');
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
CodePudding user response:
I don't understand what is controlling authenticate
to be called with google
or facebook
, I am assuming they are different buttons.
If that is the case, you need new references to the specific button elements.
it('should click google button and call authenticate method with google', () => {
spy1.withArgs('google');
// get the google button element
const googleButton = fixture.debugElement.query(By.css('button#google')).nativeElement;
googleButton.click();
expect(component.authenticate).toHaveBeenCalledWith('google');
});
it('should click facebook button and call authenticate method with facebook', () => {
spy1.withArgs("facebook");
const facebookButton = fixture.debugElement.query(By.css('button#facebook')).nativeElement;
facebookButton.click();
expect(component.authenticate).toHaveBeenCalledWith('facebook');
});
Make sure each button has a unique selector (id="facebook", id="google") or else By.css('.button-login') will find the first element it finds in the HTML matching .button-login
.