Testing a reusable component in Angular using unit testing techniques

Currently, I am creating a test for an AppleComponent which has the following type:

<T,U extends BananaComponent<T>>
. This component also contains BananaComponent<T>.

Target Component

export class AppleComponent<T,U extends BananaComponent<T>>{
   public appleA = 'appleA';
   public appleB = 'appleB';
   public appleC !: U;

}

Extended Component

export abstract class BananaComponent<T> implements OnInit{
   public bananaA = 'bananaA';
   public bananaB = 'bananaB';
}

In this case, my spec file is used to perform testing on the AppleComponent.

import { CommonModule } from '@angular/common';
import { ComponentFixture, TestBed } from '@angular/core/testing';

import {AppleComponent} from '....';
import {BananaComponent} from '....';

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

   beforeEach(()=>{
     TestBed.configureTestingModule({
         declarations:[AppleComponent],
         imports:[BananaComponent],
     });
     fixture = TestBed.createComponent(AppleComponent);
     component = fixture.componentInstance;
   });

   it('should have default values',() => {
      expect(component.appleA).toBe('appleA','appleA has appleA as default value'); // this will pass
   });
});

However, I encountered an issue with the spec file not being compilable.

After examining the logic, I realized that the types of the component and fixture were incorrect. To address this, I made some modifications as detailed below:

// Initially, define a random type within the test and assign it to AppleComponent and BananaComponent.

type typeA = { };  
type typeModel = AppleComponent<typeA, BananaComponent<typeA>>;   

let component: typeModel; 
let fixture: ComponentFixture<typeModel>

Answer №1

Have you attempted specifying the type of your component when creating it?

fixture = TestBed.createComponent<AppleComponent<TestObject>>(AppleComponent)

You may need to create a separate TestObject Model that is not compatible with generic Type T.

export class TestObject {

}

Answer №2

One aspect of this concept that tripped me up is:

AppleComponent does not directly inherit from BananaComponent, so component. cannot access properties or methods from BananaComponent.

Essentially, what's happening here is the type of AppleComponent is related to BananaComponent; The goal is to ensure that the input types in AppleComponent match those in BananaComponent.

Therefore, when testing, it is crucial to set up the component and fixture correctly.

Solution to my initial question

// Start by defining a random type within the test, then apply it to both AppleComponent and BananaComponent.

type typeA = { };  
type typeModel = AppleComponent<typeA, BananaComponent<typeA>>;   

let component: typeModel; 
let fixture: ComponentFixture<typeModel>

To better understand how the types of AppleComponent and BananaComponent interact, refer to the detailed code snippets below.

AppleComponent

export class AppleComponent<T,U extends BananaComponent<T>>{
   public appleA = 'appleA';
   public appleB = 'appleB';
   public applePurchase !: U;
}

BananaComponent

export abstract class BananaComponent<T> implements OnInit{
   public bananaA = 'bananaA';
   public bananaB = 'bananaB';
   public bananaPurchase : T;

   public totalPurchase: T;
}

The above code reveals that:

  1. In BananaComponent, type T ensures that the input value bananaPurchase matches the type of totalPurchase. For example, if bananaPurchase = 1000 (a number), then totalPurchase must also be a number.

  2. This same relationship exists in AppleComponent due to its extension of BananaComponent, indicating that applePurchase should have the same type as bananaPurchase and totalPurchase.

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

Angular HttpInterceptor Unit Test: toHaveBeenCalledWith method shows no sign of being called

I have been working on unit testing an error-handling interceptor and encountered an issue with the toHaveBeenCalledWith function. It keeps giving a "but it was never called" message in the console. Can anyone shed some light on why this might be happening ...

Is there a method for the parent to detect changes in its output when passing around complex objects to its child?

I am facing a challenge with a complex object that is being passed down from a parent component to its child components. The child components further break down this object and pass parts of it to their own children, creating layers of complexity. At times ...

Typescript's Patch<T> type enforces strictness within the codebase

There have been instances where I needed to 'patch' an object T using Object.assign(). For instance, when propagating changes you might modify a stateful object that other code references (common in reactive programming like MobX or Vue). It&ap ...

What is the best method for choosing visible elements within a scrollable container?

Is there a way to retrieve the list of visible elements within a scrollable container? The number of elements that are visible on the screen changes as one scrolls, making it challenging to add a specific class to only the last two visible elements. Any s ...

Extracting the "defined" type from a TypeScript property during runtime

My current task Presently, I am iterating through the keys of an object and transferring their values to another object. interface From { [key: string]: string; } let from: From = { prop1: "foo", prop2: "23", }; interface To { [key: str ...

Creating a custom Typescript type by leveraging Javascript variables as the key identifiers

Picture a Typescript library that serves as a database interface, giving developers the ability to specify record attributes/columns/keys to be retrieved from the database. Is it feasible to return a type that includes the keys specified by the developer? ...

Instructions for activating the "Navigate to Declaration" feature in TypeScript for JSON files using i18next

Currently, I am actively engaged in a project that involves the use of i18next with react and typescript. In this project, translation keys are defined within .json files. However, a notable drawback of transitioning to json for the translation files is l ...

Issues with Karma's base path functionality

I am encountering issues with launching tests using Karma for the first time. My folder structure is as follows: node_modules -angular-mocks src -compiled -lib -tests -karma.conf.js Within my karma.conf.js file, these are my file list and basepat ...

Warnings during npm installation such as incorrect version numbers and missing descriptions

There are some warnings appearing in the command line that I need help with: $ npm install npm WARN Invalid version: "x.0.0" npm WARN myFirstAngular2Project No description npm WARN myFirstAngular2Project No repository field. npm WARN myFirstAngular2Projec ...

Expect a reply within the loop

One of my endpoints takes some time to generate data, and I have another endpoint to retrieve that generated data. I make the initial call using await, extract the ID from the response, and then keep calling the second endpoint until the status is not "Suc ...

Sequencing API Calls: A Guide on Making Sequential API Requests

Currently, I am working on mastering RxJS. Within my project, there are 3 API calls that need to be made. Specifically, I must execute the 2nd API call and then pass its data as a parameter to the 3rd API call. My attempt at achieving this functionality is ...

Http provider not found in Angular 4 when using Rails 5 API

I recently completed a tutorial on Angular and Rails which I found here, but I am encountering difficulties in implementing it successfully. Currently, I am working with Angular version 4.2.4. [Error] ERROR Error: No provider for Http! injectionError — ...

What kind of registration does React Hook Form use?

When utilizing react-hook-form alongside Typescript, there is a component that passes along various props, including register. The confusion arises when defining the type of register within an interface: export interface MyProps { title: string; ... ...

Using TypeScript for Routing in Angular

I encountered an error message that says the module 'route' is not available. I'm not sure why this is happening, any thoughts? "Uncaught Error: [$injector:nomod] Module 'route' is not available! You either misspelled the module n ...

What is the solution for resolving an Element that implicitly has said it has an 'any' type as the expression of type 'string' cannot be used to index the type?

Having some trouble with TypeScript in my React project and encountering this error message. Error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ paymentMethod ...

Troubleshooting Angular2 Router: Version 3.0.0-alpha.8 - Issue with resolving parameters for provideRouter function

Encountering an issue while working on a project in angular2 with router version "3.0.0-alpha.8". The error message displayed during the loading of APIs states: Can't resolve all parameters for provideRouter: (?, ?) . Error : BaseException$1@http:// ...

How can we toggle a function to expand or collapse fields generated in an ngFor loop?

One of my challenges involves managing a div that is repeated using *ngFor in Angular. This results in multiple divs on the page, each containing collapsible fields that can toggle. Essentially, I have nested collapsible fields within other collapsible fie ...

Altering Angular Material Dimensions and Customizing the Appearance of md-dialog-container

Currently, I am implementing Angular Material on my website and utilizing the md-dialog component for displaying popups in my gallery. While the default animation and styling are appealing, I would like to customize the dimensions of the hidden md-dialog-c ...

AG-Grid hierarchical data structure

Transitioning from kendo tree list to ag grid tree data grid, I am facing a challenge. My table data is currently formatted as shown below, but ag grid requires data in the form of a string array of nodes in a tree. How can I adapt or customize my existing ...

Issue: The canActivateChild method in the child guard is not functioning as

Following the Angular documentation, I attempted to implement a child guard in my code: @Injectable() export class AuthGuardService implements CanActivate, CanActivateChild { constructor(private authService: AuthentificationService, private router: Rou ...