How to test Angular forms

Form validation and submission logic are critical parts of Angular applications that must be thoroughly tested to prevent user frustration and data quality issues. As the creator of CoreUI with over 12 years of Angular experience since 2014, I’ve built and tested complex forms in countless enterprise applications. Testing Angular forms involves verifying that form controls validate correctly, error messages appear at the right time, and submission handlers work as expected. The approach differs slightly between reactive forms and template-driven forms but both ensure form behavior reliability.

Test reactive forms by creating form controls, setting values, and asserting validation states and submission behavior.

import { ComponentFixture, TestBed } from '@angular/core/testing'
import { ReactiveFormsModule } from '@angular/forms'
import { LoginComponent } from './login.component'

describe('LoginComponent', () => {
  let component: LoginComponent
  let fixture: ComponentFixture<LoginComponent>

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [LoginComponent],
      imports: [ReactiveFormsModule]
    }).compileComponents()

    fixture = TestBed.createComponent(LoginComponent)
    component = fixture.componentInstance
    fixture.detectChanges()
  })

  it('should create form with email and password controls', () => {
    expect(component.loginForm.contains('email')).toBe(true)
    expect(component.loginForm.contains('password')).toBe(true)
  })

  it('should validate email format', () => {
    const emailControl = component.loginForm.get('email')

    emailControl.setValue('invalid-email')
    expect(emailControl.valid).toBe(false)
    expect(emailControl.hasError('email')).toBe(true)

    emailControl.setValue('[email protected]')
    expect(emailControl.valid).toBe(true)
  })

  it('should require password with minimum length', () => {
    const passwordControl = component.loginForm.get('password')

    passwordControl.setValue('123')
    expect(passwordControl.hasError('minlength')).toBe(true)

    passwordControl.setValue('12345678')
    expect(passwordControl.valid).toBe(true)
  })

  it('should disable submit when form is invalid', () => {
    expect(component.loginForm.valid).toBe(false)

    component.loginForm.patchValue({
      email: '[email protected]',
      password: '12345678'
    })

    expect(component.loginForm.valid).toBe(true)
  })

  it('should call onSubmit when form is submitted', () => {
    spyOn(component, 'onSubmit')

    component.loginForm.setValue({
      email: '[email protected]',
      password: '12345678'
    })

    const form = fixture.nativeElement.querySelector('form')
    form.dispatchEvent(new Event('submit'))

    expect(component.onSubmit).toHaveBeenCalled()
  })

  it('should display error message for invalid email', () => {
    const emailControl = component.loginForm.get('email')
    emailControl.setValue('invalid')
    emailControl.markAsTouched()
    fixture.detectChanges()

    const errorElement = fixture.nativeElement.querySelector('.email-error')
    expect(errorElement).toBeTruthy()
    expect(errorElement.textContent).toContain('valid email')
  })
})

Best Practice Note

Always test both valid and invalid states for each form control. Test that errors only appear after the control has been touched or the form submitted. Use patchValue for partial updates and setValue for complete form updates. Test custom validators thoroughly with edge cases. Mock HTTP services when testing form submission to avoid actual API calls. This is how we test forms in CoreUI for Angular—comprehensive coverage of validation rules, error display logic, and submission handlers to ensure robust user data collection.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
How to loop through a 2D array in JavaScript
How to loop through a 2D array in JavaScript

How to Remove Elements from a JavaScript Array
How to Remove Elements from a JavaScript Array

What is globalThis in JavaScript?
What is globalThis in JavaScript?

How to sleep in Javascript
How to sleep in Javascript

Answers by CoreUI Core Team