How to Write Unit Tests for Forms in an Angular 15 Application Using Jasmine?

Reading Time: 6 minutes
How to Write Unit Tests for Forms in an Angular 15 Application Using Jasmine?

In our previous blog, we demonstrated How to Write Unit Tests for Angular 15 Application Using Jasmine and Enforce Code Quality in a CI Workflow With Github Actions. We looked at general unit tests involving components that receive data from services. 

It is important to always ensure that Unit Tests are written in order to ensure that the quality of code being shipped to production is guaranteed to be free of any errors or bugs that can be avoided.  Writing Unit Tests also enables Continuous Integration workflows which enforce the quality of code being contributed by individual developers in teams.

In this blog, we are going to look at how we can write unit tests for Angular 15 forms. The code for the application we have used in this blog is found at https://github.com/workfall/workfall-jasmine-ng-forms. It is a simple application with forms that are filled in order to filter data about hotels from a REST API. The API is from https://rapidapi.com/tipsters/api/hotels-com-provider and you will be required to get your API key from the RapidAPI developer’s dashboard after you sign up. 

Forms Are Important but Form-Testing Is Super-Important

It is important to test forms because one is able to mimic user behavior and test whether things like form validations are working as they should. The most important part is to test form validations. Form validations include when buttons should be active or inactive, maximum characters in a text field, the maximum value in a number field, the maximum and minimum value in a date field, and also regex for special fields like passwords and emails.

Form validation is necessary to prevent malevolent users from abusing web forms. One of the leading sources of security flaws is incorrect form input validation. It makes your website vulnerable to attacks like header injections, cross-site scripting, and SQL injections.

  • Email spam may be sent from your web server using header injection techniques.
  • An attacker may use cross-site scripting to submit any data on your website.
  • SQL injection has the potential to damage your database’s backend.

Form data validation is not trivial since it is dependent on the context in which individual data items are utilized, as well as on content encoding.

Hands-On

We will be building a sample hotel booking website that has a search form that enables users to enter several search parameters to obtain information about hotels. The UI appears as shown below:

(Note the disabled button)

Write Unit Tests for Forms in an Angular 15 Application Using Jasmine

After a successful search:

Write Unit Tests for Forms in an Angular 15 Application Using Jasmine

Let us write the necessary tests for the services and also create a service stub and mock data which will be used in component unit tests. Then make sure to import all the necessary modules into all the component testing modules before running the ng test –code-coverage command. This will generate a coverage folder in your project and you can serve the HTML file using a live server in VS Code.

api.service.mock-data.ts:

Write Unit Tests for Forms in an Angular 15 Application Using Jasmine

api.service.spec.ts:

Write Unit Tests for Forms in an Angular 15 Application Using Jasmine

api.service.spec.ts(2):

Write Unit Tests for Forms in an Angular 15 Application Using Jasmine

That will be it for services tests. Next, we shall create a service stub which we’ll use to test our components. Remember that it is never a good idea to inject the service directly into the Testing Module; always use a stub which is just an ES6 class with the same methods and return types as the service we are mocking.

api.service.stub.ts:

Next, we shall create our form which we shall use to create a search query for hotel data. We shall create a lazy-loaded module(HomeModule) that contains the HomeComponent.

home.component.html:

Write Unit Tests for Forms in an Angular 15 Application Using Jasmine

home.component.html(2):

home.component.ts:

home.component.ts(2):

In this section, you will notice that we are debouncing our API calls using RXJS on the searchbox to prevent server overloads (Look at the AfterViewInit hook).

Write Unit Tests for Forms in an Angular 15 Application Using Jasmine

home.component.ts(3):

We shall also create a hotel card component just to neatly display the hotel data that we shall get from the search results. We shall pass the data for this component from the parent component i.e HomeComponent.

hotel-card.component.html:

Write Unit Tests for Forms in an Angular 15 Application Using Jasmine

hotel-card.component.ts:

To make sure that the failing test as shown in the screenshot above is passing, define the component.data prop in the component test bed as shown below.

Now let’s check our coverage report.

At this point, it is only the forms that need extra work to make sure that we reach the ~100% score in terms of test coverage. One important thing to note is that it will be advisable to use HTML IDs to target DOM elements while writing Unit Tests because they are unique.

home.component.spec.ts:

It is very important to note that we are providing the Service Stub here

home.component.spec.ts(2):

We are wrapping the callback in a fakeAsync HOF(Higher order function) to mimic the debouncing behavior we have on the search field and finally using tick to simulate elapse of the debounce time

home.component.spec.ts(3):

home.component.spec.ts(4):

Conclusion

In this blog, we demonstrated how to write unit tests for various form elements such as select fields, and input fields and also how to validate forms in Unit Tests. We also looked at how we can mimic asynchronous behavior in our tests using fakeAsync and tick from RXJS. 

The coverage report can get to 100% by looking at all branching code cases i.e ensuring all conditionals such as if statements and ternary operators are covered and sometimes this can be achieved by creating test suites that are similar but with different sets of mock data.

Summary:

  • Writing Unit Tests for form elements by triggering events
  • Validating forms while writing Unit tests.
  • Writing Unit Tests for asynchronous code.

We will come up with more such use cases in our upcoming blogs.

Meanwhile…

If you are an aspiring Angular Lover and want to explore more about the above topics, here are a few of our blogs for your reference:

Stay tuned to get all the updates about our upcoming blogs on the cloud and the latest technologies.

Keep Exploring -> Keep Learning -> Keep Mastering 

At Workfall, we strive to provide the best tech and pay opportunities to kickass coders around the world. If you’re looking to work with global clients, build cutting-edge products and make big bucks doing so, give it a shot at workfall.com/partner today!

Back To Top