Reputation: 58
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:
export class LoginPageComponent {
constructor(
protected loginServices: LoginServices,
private router: Router,
private toastServices: ToastServices
) {}
protected loginInfo: LoginInfo = this.loginServices.loginInfo;
LoginPageComponent HTML:
<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:
export class LoginServices {
constructor(private http: HttpClient) {}
public loginInfo: LoginInfo = new LoginInfo('', '');
}
LoginInfo:
export class LoginInfo {
constructor(public email: string, public password: string) {}
public isReadyToSubmit(): boolean {
return this.email !== '' && this.password !== '';
}
}
LoginPageComponent spec:
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();
});
});
Upvotes: 1
Views: 38
Reputation: 56052
NgModel
will work fine so there is no need to trigger an artificial event, we can directly update the properties that are binded to ngModel and then check disabled.
it('should enable Login button when there are email and password inputs', async () => {
const data = {
email: '[email protected]',
password: '123',
};
component.loginInfo.email = data.email;
component.loginInfo.password = data.password;
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(loginButton.disabled).toBeFalse();
});
});
Upvotes: 0