Guide to creating a Unit Test for an Angular Component with a TemplateRef as an Input

Looking to create unit tests for an Angular component that can toggle the visibility of contents passed as input. These inputs are expected to be defined as TemplateRef.

my-component.component.ts

@Component({
    selector: "my-component",
    templateUrl: "./my-component.component.html",
    styleUrls: ["./my-component.component.scss"],
    exportAs: "mycomponent"
})
export class MyComponent {
    private _expanded = false;

    @Input()
    set expanded(value: boolean) {
        this._expanded = value;
    }

    @Input()
    body: TemplateRef<any>;
    @Input()
    handler: TemplateRef<any>;

    constructor() {}

    toggleView() {
        this.expanded = !this._expanded;
    }
}

my-component.component.html

<div class="wrap">
    <!-- Header -->
    <main #header>
        <header (click)="toggleAccordion()">
            <div class="handler">
                <ng-container [ngTemplateOutlet]="handler">
                </ng-container>
            </div>
            <i class="icon icon-expand" [ngClass]="{ 'icon-expand': _expanded, 'icon-collapse': !_expanded }"></i>
        </header>
    </main>
    <!-- Body -->
    <div class="body" *ngIf="_expanded">
        <ng-container [ngTemplateOutlet]="body"></ng-container>
    </div>
</div>

I'm trying to test whether the content passed through the "body" input is visible or not, but I'm struggling with how to instantiate a "my-component" with a TemplateRef input in Jasmine.

The Angular documentation provides information on passing an input in the unit test script, but because TemplateRef is an abstract class, I'm unsure how to proceed.

my-component.component.spec.ts


...

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [MyComponent]
        }).compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(MyComponent);
        component = fixture.componentInstance;
        component.body = /* What should I put here? */;
        fixture.detectChanges();
    });

....

Answer №1

Here is a demo code that you can build upon:

To properly test your component, you will need to approach it differently. Since creating your component without utilizing the TemplateRef of another component is not possible, you should create a wrapper component and then write test cases for the WrapperComponent.


@Component({
  template: `
    <ng-template #div1>Something here</ng-template>
    <ng-template #div2>Many things here</ng-template>
    <my-component [expanded]="expandedVal" [body]="div1" [handler]="div2"> </my-component>
  `,
})
class WrapperComponent {
     @ViewChild(MyComponent, { static: true }) appComponentRef: MyComponent;
     public expandedVal = true;
}

describe('MyComponent', () => {
  let app: MyComponent;
  let fixture: ComponentFixture<WrapperComponent>;
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [WrapperComponent, MyComponent],
    }).compileComponents();
  }));
  beforeEach(() => {
    fixture = TestBed.createComponent(WrapperComponent);
    const wrapperComponent = fixture.debugElement.componentInstance;
    app = wrapperComponent.appComponentRef; // This is how you access the "MyComponent" for testing
    fixture.detectChanges();
  });
  it('should create the app', async(() => {
    expect(app).toBeDefined();
  }));
});

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

Error in Typescript index: iterating over properties of a typed object

My scenario involves an interface that extends multiple other interfaces from an external library: interface LabeledProps extends TextProps, ComponentProps { id: string; count: number; ... } In a different section of the codebase, there is an ...

Having trouble locating a file in WebStorm? Try accessing WebStorm through the terminal instead

Starting WebStorm from the terminal Version: WebStorm 2016.3.3 I suspect that the reason it's not functioning is due to emojis in some of my file names. Do you think this could be the issue, or is there another root cause for the problem? Can emoji ...

Setting up the propTypes for interface in React TypeScript

How can I specify the correct PropTypes for a property that is an interface in TypeScript with PropTypes? Requirements - Implementing both TS and PropTypes. Goal - To have a more precise type definition than PropTypes.any that meets standard eslint an ...

Choosing specific information in Typescript response

I am encountering an issue with my HTML where it displays undefined(undefined). I have checked the data in the debugger and I suspect that there may be an error in how I am using the select data. Here is a snippet of the code: <div *ngIf="publishIt ...

Tips for achieving server-side pagination with client-side sorting

Currently utilizing Angular Material's data grid, successfully loading data from the server side with sorting and pagination functionality. However, I am attempting to sort only the items visible on the table instead of sorting from the server side. ...

Retrieving source in Angular from an async function output within a specified time limit

I have a quick query :). I'm attempting to retrieve the image src from an async function, but so far, I haven't had much success. This is what I have: <img [src]="getProductImage(articleNumber)"/> and in my TypeScript file: publi ...

Eliminating null values from a multidimensional array

Is there a way to remove the array elements cctype, cctypologycode, and amount if they are empty? What would be the most efficient approach? { "ccInput": [ { "designSummaryId": 6, "CCType": "A", "CCTypologyCode": "A", "Amount ...

Facing a continuous issue where the Angular Universal Bundle keeps loading but only displays a

As I attempted to convert a basic Angular application into a universally supported application, I made all the necessary changes such as adding checks on DOM elements like window, navigator, setTimeout, etc. After running the command npm run build:ssr &am ...

What advantages do interfaces as data types offer in Angular compared to using classes?

After watching a tutorial from my teacher, he showed us this code snippet: He mentioned that the products array, defined as type any [], is not taking advantage of TypeScript's strongly typing. He suggested using an INTERFACE instead. I have a questi ...

Eliminating the "undefined" error in TypeScript within a React application

Having recently dived into TypeScript configuration, I encountered an issue when coding and tried to resolve it by encapsulating the code block in an if statement checking for usersData to eliminate the "Object is possibly undefined" errors. However, upon ...

I'm having trouble resolving this issue with an Unexpected Application Error! It seems that I cannot set the property value of #<TextFieldBase2> since it only has a

Currently, I'm utilizing TypeScript, React Hook Form, Yup validation, and Fluent UI. Every time I attempt to submit a form, I encounter the error 'Unexpected Application Error! Cannot set property value of # which has only a getter'. https:/ ...

The variable 'form' has not been assigned an initial value in the constructor of the property

Below is the snippet from my component.ts file: import { Component, OnInit } from '@angular/core'; import { Validators, FormControl, FormGroup, FormBuilder } from '@angular/forms'; @Component({ selector: 'app-license', te ...

The parameter "path" must be a string type. Instead, we received type undefined. This issue is specific to Ionic 4 on Windows

Encountered an unexpected error that is hindering development on a Windows PC, even though building the app works fine on a Mac. The error message received is: cordova build android --stacktrace config file undefined requested for changes not found at ...

Ways to utilize the ::after pseudo class with ElementRef within Angular

Is it possible to manipulate the background-color of the ::after pseudo selector for the specified element using Angular? @ViewChild('infobubble', { read: ElementRef }) infoBubbleElement: ElementRef; ngAfterViewInit(): void { const el ...

Incorporating XMLHttpRequest in my React Typescript App to trigger a Mailchimp API call, allowing users to easily sign up for the newsletter

My website needs to integrate Mailchimp's API in order for users to subscribe to a newsletter by entering their email into a field. I am looking to implement this without relying on any external libraries. To test out the functionality, I have set up ...

Having trouble with Angular CLI on your Windows 10 system?

Recently, I reinstalled node.js, npm, and angular-cli on my Windows 10 PC. However, after installing angular-cli using the command npm install -g @angular/cli, I encountered an issue. Despite having node.js version 8.1.2 and npm version 5.0.3, whenever I t ...

Putting in Angular's most recent version

While attempting to update to the latest version of angular/cli, I encountered an error: npm install --save-dev @angular/cli@latest npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.2 (node_modules\chokidar\node_modules\fs ...

Is it possible to use TypeScript in a React Native project with a JavaScript file?

Currently, I am learning React Native by working on app clones like Instagram and YouTube. I have recently started an AirBnb clone project, but I'm facing some issues with the initial build. One issue I noticed is that in 'App.js', the temp ...

The function __WEBPACK_IMPORTED_MODULE_3_ionic_native__.a.open is returning an error

Is there a way to troubleshoot and resolve the following error: WEBPACK_IMPORTED_MODULE_3_ionic_native.a.open is not a function while utilizing the NishanthKabra/Ionic2_GoogleCalendar solution. I am interested in integrating Google Calendar into my Io ...