I have a LoginPageComponent
with email
and password
fields whose values areNgModel
binded to LoginServices
‘s property loginInfo
. LoginPageComponent
also has Login
button, which is disabled when loginInfo.isReadyToSubmit()
returns false
(when either email or password is empty).
In my unit test for LoginPageComponent
, I want to verify that Login
button is enabled when loginInfo.isReadyToSubmit()
returns true
.
I tried dispatchEvent()
, detectChange()
, and fixture.whenStable().then()
but nothing seems to work. How should I proceed from here? I am happy to take correction/criticism in other aspects of my code.
LoginPageComponent:
<code>export class LoginPageComponent {
protected loginServices: LoginServices,
private toastServices: ToastServices
protected loginInfo: LoginInfo = this.loginServices.loginInfo;
<code>export class LoginPageComponent {
constructor(
protected loginServices: LoginServices,
private router: Router,
private toastServices: ToastServices
) {}
protected loginInfo: LoginInfo = this.loginServices.loginInfo;
</code>
export class LoginPageComponent {
constructor(
protected loginServices: LoginServices,
private router: Router,
private toastServices: ToastServices
) {}
protected loginInfo: LoginInfo = this.loginServices.loginInfo;
LoginPageComponent HTML:
<code><div class="route-container">
<spinner [isDisplayed]="loginServices.isLoggingIn()" />
<form #loginForm="ngForm" (ngSubmit)="onSubmit()">
<input type="email" [(ngModel)]="loginInfo.email" name="email" />
<input type="password" [(ngModel)]="loginInfo.password" name="password" />
[disabled]="!loginInfo.isReadyToSubmit() || loginServices.isLoggingIn()"
<code><div class="route-container">
<spinner [isDisplayed]="loginServices.isLoggingIn()" />
<form #loginForm="ngForm" (ngSubmit)="onSubmit()">
<label>
Email <br />
<input type="email" [(ngModel)]="loginInfo.email" name="email" />
</label>
<br /><br />
<label>
Password <br />
<input type="password" [(ngModel)]="loginInfo.password" name="password" />
</label>
<br /><br />
<div class="center">
<button
type="submit"
[disabled]="!loginInfo.isReadyToSubmit() || loginServices.isLoggingIn()"
>
Login
</button>
</div>
</form>
</div>
</code>
<div class="route-container">
<spinner [isDisplayed]="loginServices.isLoggingIn()" />
<form #loginForm="ngForm" (ngSubmit)="onSubmit()">
<label>
Email <br />
<input type="email" [(ngModel)]="loginInfo.email" name="email" />
</label>
<br /><br />
<label>
Password <br />
<input type="password" [(ngModel)]="loginInfo.password" name="password" />
</label>
<br /><br />
<div class="center">
<button
type="submit"
[disabled]="!loginInfo.isReadyToSubmit() || loginServices.isLoggingIn()"
>
Login
</button>
</div>
</form>
</div>
LoginServices:
<code>export class LoginServices {
constructor(private http: HttpClient) {}
public loginInfo: LoginInfo = new LoginInfo('', '');
<code>export class LoginServices {
constructor(private http: HttpClient) {}
public loginInfo: LoginInfo = new LoginInfo('', '');
}
</code>
export class LoginServices {
constructor(private http: HttpClient) {}
public loginInfo: LoginInfo = new LoginInfo('', '');
}
LoginInfo:
<code>export class LoginInfo {
constructor(public email: string, public password: string) {}
public isReadyToSubmit(): boolean {
return this.email !== '' && this.password !== '';
<code>export class LoginInfo {
constructor(public email: string, public password: string) {}
public isReadyToSubmit(): boolean {
return this.email !== '' && this.password !== '';
}
}
</code>
export class LoginInfo {
constructor(public email: string, public password: string) {}
public isReadyToSubmit(): boolean {
return this.email !== '' && this.password !== '';
}
}
LoginPageComponent spec:
<code>describe('LoginPageComponent', () => {
let component: LoginPageComponent;
let fixture: ComponentFixture<LoginPageComponent>;
let emailInput: HTMLInputElement;
let passwordInput: HTMLInputElement;
let loginButton: HTMLButtonElement;
let loginServices: LoginServices;
await TestBed.configureTestingModule({
MatProgressSpinnerModule,
declarations: [NgModel, NgForm, SpinnerComponent, LoginPageComponent],
providers: [{ provide: LoginServices }],
fixture = TestBed.createComponent(LoginPageComponent);
component = fixture.componentInstance;
loginServices = TestBed.inject(LoginServices);
const nativeElement: HTMLElement = fixture.nativeElement;
emailInput = nativeElement.querySelector('input[name="email"]')!;
passwordInput = nativeElement.querySelector('input[name="password"]')!;
loginButton = nativeElement.querySelector('button')!;
it('should enable Login button when there are email and password inputs', async () => {
email: '[email protected]',
emailInput.value = data.email;
emailInput.dispatchEvent(new Event('input'));
passwordInput.value = data.password;
passwordInput.dispatchEvent(new Event('input'));
fixture.whenStable().then(() => {
expect(loginButton.disabled).toBeFalse();
<code>describe('LoginPageComponent', () => {
let component: LoginPageComponent;
let fixture: ComponentFixture<LoginPageComponent>;
let emailInput: HTMLInputElement;
let passwordInput: HTMLInputElement;
let loginButton: HTMLButtonElement;
let loginServices: LoginServices;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
HttpClientModule,
ToastrModule.forRoot(),
MatProgressSpinnerModule,
],
declarations: [NgModel, NgForm, SpinnerComponent, LoginPageComponent],
providers: [{ provide: LoginServices }],
}).compileComponents();
fixture = TestBed.createComponent(LoginPageComponent);
component = fixture.componentInstance;
loginServices = TestBed.inject(LoginServices);
fixture.detectChanges();
const nativeElement: HTMLElement = fixture.nativeElement;
emailInput = nativeElement.querySelector('input[name="email"]')!;
passwordInput = nativeElement.querySelector('input[name="password"]')!;
loginButton = nativeElement.querySelector('button')!;
});
it('should enable Login button when there are email and password inputs', async () => {
const data = {
email: '[email protected]',
password: '123',
};
emailInput.value = data.email;
emailInput.dispatchEvent(new Event('input'));
fixture.detectChanges();
passwordInput.value = data.password;
passwordInput.dispatchEvent(new Event('input'));
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(loginButton.disabled).toBeFalse();
});
});
</code>
describe('LoginPageComponent', () => {
let component: LoginPageComponent;
let fixture: ComponentFixture<LoginPageComponent>;
let emailInput: HTMLInputElement;
let passwordInput: HTMLInputElement;
let loginButton: HTMLButtonElement;
let loginServices: LoginServices;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
HttpClientModule,
ToastrModule.forRoot(),
MatProgressSpinnerModule,
],
declarations: [NgModel, NgForm, SpinnerComponent, LoginPageComponent],
providers: [{ provide: LoginServices }],
}).compileComponents();
fixture = TestBed.createComponent(LoginPageComponent);
component = fixture.componentInstance;
loginServices = TestBed.inject(LoginServices);
fixture.detectChanges();
const nativeElement: HTMLElement = fixture.nativeElement;
emailInput = nativeElement.querySelector('input[name="email"]')!;
passwordInput = nativeElement.querySelector('input[name="password"]')!;
loginButton = nativeElement.querySelector('button')!;
});
it('should enable Login button when there are email and password inputs', async () => {
const data = {
email: '[email protected]',
password: '123',
};
emailInput.value = data.email;
emailInput.dispatchEvent(new Event('input'));
fixture.detectChanges();
passwordInput.value = data.password;
passwordInput.dispatchEvent(new Event('input'));
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(loginButton.disabled).toBeFalse();
});
});