Unit testing the TypeScript function with Karma, which takes NgForm as a parameter

As I work on writing unit tests for a specific method, I encounter the following code:

public addCred:boolean=true;
public credName:any;

public addMachineCredential(credentialForm: NgForm) {
    this.addCred = true;
    this.credName = credentialForm.value.name;
}

When attempting to test this function in my test class, I run into an issue:

it('should add machine credential', () => {
    var machineCredentialForm: NgForm = new NgForm(null, null);
    machineCredentialForm.controls['name'].setValue('name');
    machineCredentialForm.controls['username'].setValue('username');
    machineCredentialForm.controls['password'].setValue('password');
    component.addMachineCredential(machineCredentialForm);
    expect(component.addCred).toBe(true);
    expect(component.credName).toBe("name");
});

An error occurs stating:

TypeError: Cannot read property 'setValue' of undefined

I am seeking advice on properly testing the "addMachineCredential" function.

Answer №1

If you want to perform unit testing on the module, it is recommended to utilize ReactiveForms instead of Template driven forms as suggested in the comment. I have refactored the code and provided an example based on the snippet you shared. Here is a possible solution:

Here is one approach to refactor your code to ensure its functionality:

Your component:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';

@Component({
  selector: 'app-unit-test',
  template: `
  <p>Works</p>
  `,
  styleUrls: ['./unit-test.component.css']
})
export class UnitTestComponent {
  public addCred: boolean = true;
  public credName: any;

  form: FormGroup = new FormGroup({
    name: new FormControl('', [])
  });

  constructor() {}

  public addMachineCredential(credentialForm: FormGroup) {
    this.addCred = true;
    this.credName = credentialForm.controls.name.value;
  }
}

Your spec file:

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { UnitTestComponent } from './unit-test.component';

fdescribe('UnitTestComponent', () => {
  let component: UnitTestComponent;
  let fixture: ComponentFixture<UnitTestComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [UnitTestComponent],
      imports: [FormsModule, ReactiveFormsModule]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(UnitTestComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should add machine credential', () => {
    component.form.controls.name.setValue('name');
    component.addMachineCredential(component.form);
    expect(component.addCred).toBe(true);
    expect(component.credName).toBe('name');
  });
});

Keep in mind that your component module must declare ReactiveFormsModule, so..

Your module:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { UnitTestComponent } from './Questions/unit-test/unit-test.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

@NgModule({
  declarations: [
    AppComponent,
    UnitTestComponent,
    FormsModule,
    ReactiveFormsModule
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

I hope this explanation proves helpful.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Adjusting the width of row items in Angular by modifying the CSS styles

I am envisioning a horizontal bar with items that are all the same width and evenly spaced apart. They can expand vertically as needed. Check out the updated version here on StackBlitz Issue: I am struggling to automatically set the width of the row elem ...

"Loop through an array using forEach leads to a subscription that

I am a beginner in Angular and struggling to understand how async functions work. I have written the following code, but I am encountering an error: GET https://localhost:44353/api/ecams/id/undefined 400 and ["The value 'undefined' is not va ...

How to leverage async/await within loops in Node.js for optimized performance and efficiency

Hey there, I'm working on my nodejs api where I need to fetch data inside a loop and then perform another loop to save data in a different table. Can anyone guide me on how to achieve this? Below is a snippet of what I have attempted so far without su ...

Create a custom component that wraps the Material-UI TextField component and includes default

I have been exploring React and had a question regarding wrapping a component like TextField from mui to add new props along with the existing ones. I attempted to do this but am struggling to figure out how to access the other props. Can anyone help me ...

Alter the class based on the incoming string from the rxjs stream

I have a stream that outputs strings, and based on these strings I want to apply certain classes to a specific tag: If the string is "ok", add class "fa-check" If the string is "loading", add classes "fa-spin" and "fa-spinner" If the string is "error", a ...

Error encountered when using Typescript with SvelteKit and Supabase data retrieval (Cannot assign type 'null' to type 'ArrayLike<unknown>')

My SvelteKit project is configured to authenticate with supabase. I followed this guide for the setup. Authentication and data fetching are working smoothly so far. However, I'm encountering a persistent Typescript error that I can't seem to reso ...

Issue with dynamic HTML preventing Bootstrap tooltip functionality

There's an HTML page where a section is dynamically generated through HTML injection from a typescript angularjs controller using $sce and ng-bind-html. The issue is that the custom bootstrap tooltip style doesn't seem to be applied, and only t ...

The type 'Text' does not have a property named 'then'

Transitioning from .js to typescript. When I changed the file extension from .js to .ts while keeping the same code, I encountered an error stating Property 'then' does not exist on type 'Text'.ts in the then((value) method. The return ...

The component is not being activated by the subject subscribe

I'm having trouble subscribing to the Subject folder_id in the board component when passing the id from the files component. The boardId function is called when a button is pressed in the files component. The activateId is retrieved from the URL snap ...

"Converting array into a string in TypeScript/Javascript, but unable to perform operations

After generating a string with the correct structure that includes an array, I am able to navigate through the JSON on sites like However, when attempting to access the array, it turns out that the array itself is null. Here is the scenario: Firstly, th ...

The specified React element type is not valid

Currently working on a web application using Typescript, Electron, Webpack, and NodeJS, but encountering issues with the import/export functionality. The error message that I am facing reads: "Warning: React.createElement: type is invalid -- expect ...

Issue with border radius in MUI 5 affecting table body and footer elements

Currently, I am diving into a new project utilizing React version 18.2 and MUI 5.10.3 library. My main task involves designing a table with specific styles within one of the components. The table header should not display any border lines. The table body ...

When converting an object into a specific type, the setter of the target type is not invoked

Imagine a scenario with a class structured like this: class Individual { private _name: string; get Name(): string { return this._name; } set Name(name: string) { this._name = name; } } Upon invoking HttpClient.get<Individual>(), it retrieve ...

Transforming file location to base64 encoded format using TypeScript

I have the path of an image and need to convert it to base64 format, similar to this data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUg... function encodeImageToBase64(url, callback) { var xhr = new XMLHttpRequest(); xhr.onload = function() { va ...

Navigating with Angular's router occurs before the guard is fully completed

Within my Angular 8 application, the routing file is structured as below: const myRoutes: Routes = [ {path: '', component: FirstComponent , canActivate: [RegistrationSrcdGuard]}, {path: 'FirstComponent ', component: FirstCompon ...

Assigning IDs to Values in Angular 2

Here is the code snippet in question: <select [(ngModel)]=""> <option value="1">New York</option> <option value="2"Phoenix</option> <option value="3">Boston</o ...

Error: Unable to retrieve data - Angular2 application encountered a XHR error with status code 404 (

Hey there, I recently started working with angularjs and created a demo app using angular2. However, when I try to run the application, I encounter an error. Interestingly, even though the error mentions a 404 status code, if I visit the URL http://loc ...

Modify a property within an object and then emit the entire object as an Observable

I currently have an object structured in the following way: const obj: SomeType = { images: {imageOrder1: imageLink, imageOrder2: imageLink}, imageOrder: [imageOrder1, imageOrder2] } The task at hand is to update each image within the obj.images array ...

What distinguishes Angular directives as classes rather than functions?

When using Ng directives within HTML tags (view), they appear to resemble functions that are called upon rather than instances of a class. It almost feels like they could be static methods that can be invoked without an instance of a class. Comin ...

Need assistance with the Angular polyfill.ts file? Wondering where to place the polyfill code and how to manage it effectively?

Currently encountering an error in my Angular project that requires some 'polyfilling'. Due to the restriction on editing webpack.config.js directly, it seems necessary to work with the polyfill.ts file instead. The issue lies in the fact that An ...