Error: Attempting to access properties of an undefined value (cannot read property '_hostElement')

I'm currently working on a project and trying to incorporate unit tests into it, but I'm facing difficulties in getting a specific component to be generated.

My Angular version is 15.1.3 and I can't seem to figure out what might be causing the issue. Whenever I call fixture.detectChanges();, I receive an error message saying

TypeError: Cannot read properties of undefined (reading '_hostElement')
.

Below are the sections of code that I believe are relevant:

loot-generator.component.spec.ts

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

import { LootGeneratorComponent } from './loot-generator.component';
import { Clipboard } from '@angular/cdk/clipboard';
import { MatSnackBar } from '@angular/material/snack-bar';
import { MatCard, MatCardActions, MatCardContent, MatCardHeader, MatCardTitle } from '@angular/material/card';
import { MatSlideToggle } from '@angular/material/slide-toggle';
import { MatSlider, MatSliderVisualThumb } from '@angular/material/slider';
import { FormsModule } from '@angular/forms';
import { MatRippleModule } from '@angular/material/core';

describe('LootGeneratorComponent', () => {
  let component: LootGeneratorComponent;
  let fixture: ComponentFixture<LootGeneratorComponent>;
  const snackBarSpy = jasmine.createSpyObj('MatSnackBar', ['open']);
  const clipboardSpy = jasmine.createSpyObj('Clipboard', ['beginCopy']);

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [ FormsModule, MatRippleModule ],
      declarations: [
        LootGeneratorComponent,
        MatCard,
        MatCardHeader,
        MatCardTitle,
        MatCardContent,
        MatSlideToggle,
        MatSlider,
        MatCardActions,
        MatSliderVisualThumb
      ],
      providers: [
        {provide: MatSnackBar, useValue: snackBarSpy},
        {provide: Clipboard, useValue: clipboardSpy}
      ]
    })
    .compileComponents();

    fixture = TestBed.createComponent(LootGeneratorComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();  // Error is shown here 'TypeError: Cannot read properties of undefined (reading '_hostElement')
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

loot-generator.component.ts

import { Component } from '@angular/core';
import { CoinType } from './enums/coin.enum';
import { TreasureType } from './enums/treasure.enum';
import { Loot } from './models/loot.model';
import { TreasureGenerator } from './services/treasure-generator.service';
import { Clipboard } from '@angular/cdk/clipboard';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Coin } from './models/coin.model';
import { ICoin } from './interfaces/coin.interface';
import { Treasure } from './models/treasure.model';

@Component({
  selector: 'app-loot-generator',
  templateUrl: './loot-generator.component.html',
  styleUrls: ['./loot-generator.component.css']
})
export class LootGeneratorComponent {
  private generator: TreasureGenerator = new TreasureGenerator();

  public challengeRating: number = 1;
  public groupLoot: boolean = false;
  public displayedColumns: string[] = ['coin', 'amount']
  public displayTreasureColumns: string[] = ['treasure', 'name', 'value']
  public loot: Loot = new Loot();

  constructor(
    private clipboard: Clipboard,
    private snackBar: MatSnackBar) {}

// ... bunch 'o methods which are omitted for brevity. I doubt they are the issue as they aren't even called yet

loot-generator.html

<mat-card class="card">
  <mat-card-header>
    <mat-card-title>Loot Generation Options</mat-card-title>
  </mat-card-header>
  <mat-card-content>
    <section class="options">
      <div>
        <mat-slide-toggle [(ngModel)]="groupLoot" name="groupLoot">Hoard Loot</mat-slide-toggle>
      </div>
      <div>
        <mat-slider class="slider" min="1" max="20" step="1" discrete>
          <input matSliderThumb [(ngModel)]="challengeRating">
        </mat-slider>
        <label id="slider-name-label" class="slider-name-label">CR</label>
        <label id="slider-value-label" class="slider-value-label">
        {{challengeRating}}
        </label>
      </div>
    </section>
    <mat-card-actions class="options-buttons">
      <button
        mat-flat-button
        color="primary"
        (click)="generateLoot()">Generate</button>
      <button
        mat-flat-button
        color="accent"
        (click)="clear()">Clear</button>
    </mat-card-actions>
  </mat-card-content>
</mat-card>

<mat-card class="card" *ngIf="loot.coins.length > 0 || loot.treasures.length > 0">
  <mat-card-header>
        <button
          mat-icon-button
          matTooltip="Copy to clipboard"
          aria-label="Copy to clipboard"
          (click)="onCopyToClipboardClick()">
          <mat-icon>content_copy</mat-icon>
        </button>
        <button
          mat-icon-button
          matTooltip="Sell Loot"
          aria-label="Sell Loot"
          (click)="onSellClick()">
          <mat-icon>sell</mat-icon>
        </button>
  </mat-card-header>
  <mat-card class="card" *ngIf="loot.coins.length > 0">
    <table
      #coinTable
      *ngIf="loot.coins.length > 0"
      mat-table
      id="0"
      [dataSource]="loot.coins">

      <ng-container matColumnDef="coin">
        <th mat-header-cell *matHeaderCellDef> Coin </th>
        <td mat-cell *matCellDef="let element"> {{getCoinName(element.type)}} </td>
      </ng-container>

      <ng-container matColumnDef="amount">
        <th mat-header-cell *matHeaderCellDef> Amount </th>
        <td mat-cell *matCellDef="let element"> {{element.amount}}</td>
      </ng-container>

      <ng-container matColumnDef="action">
        <th mat-header-cell *matHeaderCellDef> Action </th>
        <td mat-cell *matCellDef="let element">
          <button mat-flat-button>Re-Roll</button>
        </td>
      </ng-container>

      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>
  </mat-card>

  <mat-card class="card" *ngIf="loot.treasures.length > 0">
    <table
      #treasureTable
      *ngIf="loot.treasures.length > 0"
      mat-table
      id="1"
      [dataSource]="loot.treasures">

      ....more HTML code....
      
    </table>
    </mat-card>
    <mat-card-actions>
    </mat-card-actions>
</mat-card>

Answer №1

When generating the component you're testing, an error is occurring. It's likely that this error is related to the required material components that are included.

Typically, I stub library components, but I recently came across some information that might help:

The abstract base class for all component harnesses is ComponentHarness. Each harness extends this class, and every ComponentHarness subclass has a static property called hostSelector, which identifies instances of the component in the DOM. The API for each harness is specific to its corresponding component; consult the component's documentation for guidance on using a particular harness

If you're facing issues, it could be beneficial to check out this resource (which includes an overview and API section similar to standard material component documentation): https://material.angular.io/cdk/test-harnesses/overview#component-test-harnesses

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

Switching the LOCALE_ID in angular at runtime

One example of extensive localization support is found in the FB region setting, which accommodates hundreds of locales. How can we replicate this functionality in Angular? Would this require us to manually register all supported locales during development ...

Guide to displaying the value of a field in an object upon clicking the inline edit button using TypeScript

Is it possible to console log a specific attribute of an object when clicking on the edit button using the code below? Please provide guidance on how to utilize the index to access the value of "name". Refer to the last line in the code with the comment. ...

npm - Configuring the maximum memory usage in npm

I encountered an error message while trying to build my Angular project, The error states: "CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory" I read somewhere that adjusting the max-old-space-size in npm could resolve this issue. How ...

Notify user before exiting the page if there is an unsaved form using TypeScript

I am working on a script that handles unsaved text inputs. Here is the code for the script: export class Unsave { public static unsave_check(): void { let unsaved = false; $(":input").change(function(){ unsaved = true; ...

In TypeScript, is there a similar concept to "sealed" or "final" modifiers?

I'm currently working on incorporating a method in a superclass that should be accessible for use, but not modifiable, in subclasses. Take a look at the following: export abstract class BaseClass { universalBehavior(): void { doStuff(); / ...

Utilizing Json Service in Liferay with Angular2

After attempting to integrate Angular 2 into Liferay 7, I am facing difficulties with consuming json services. The issue may be related to the multitude of 404 errors occurring due to node_modules not being found under /web/guest. An example can be seen he ...

A guide to mocking axios in React by leveraging the axios.create function

Currently, I am working on a React project where I am utilizing axios for handling http requests. To manage the axios configuration, I have set up a separate file with the following setup: import axios from 'axios' export default axios.create({ ...

How can I transfer an instance of a class to dataTransfer.setData?

So I created a new instance of a class: let item = new Item(); Next, I attempted to serialize the item and add it to dataTransfer for drag and drop functionality: ev.dataTransfer.setData("info", JSON.stringify(item)); At some point, I need to retriev ...

Guide on Importing All Functions from a Custom Javascript File

As a beginner in learning Angular, I am faced with the task of converting a template into Angular. However, I am struggling to find a solution for importing all functions from a custom js file into my .component.ts file at once. I have already attempted t ...

Encountering an issue with PrimeNG's <p-calendar> component: the error message "date

I encountered an issue resulting in the following error message: core.es5.js:1020 ERROR Error: Uncaught (in promise): TypeError: date.getMonth is not a function TypeError: date.getMonth is not a function This error occurs whenever I attempt to implement ...

What could be causing TypeScript to forego type inference and default to 'any' in this scenario?

While refactoring parts of our React app in TypeScript, I encountered a challenge that required me to use what I consider to be a less than ideal double type argument. I'm unsure if this is a bug in TypeScript or if there is some type ambiguity causin ...

Improved with TypeScript 4.1: Fixed-Size String Literal Type

The latest updates from the TypeScript team have shown significant improvements in string literal typing (4.1 & 4.2). I'm curious if there's a way to define a fixed length string. For example: type LambdaServicePrefix = 'my-application- ...

We are currently unable to identify the specific web framework being used. For further details, please refer to the firebase-debug

I encountered an issue during the deployment process of my Angular application to Firebase Hosting using the firebase deploy command. The error message I received is as follows: [2024-01-31T22:26:15.400Z] --------------------------------------------------- ...

Facing a blank page with no errors displayed during the HTML rendering process in Angular version 6

One of the most frustrating aspects of working with Angular is the lack of information provided when there is a render error in an HTML page. Instead of specifying which page the error is in, Angular defaults to the route page and provides no further detai ...

Allow only numerical values through an ion-input in Ionic 4, preventing the input of letters and special characters

I am currently developing an application in Ionic 4 that requires users to enter only integer numbers (0-9). I need to prevent any other characters such as alphabets, dots, or plus signs from being entered. However, the methods I have tried so far have not ...

Creating an array by extracting form values in Angular

In my component, I have the following function: updateInfo(info: NgForm) { const changedValues = Object.keys(info.controls) .filter(key => info.controls[key].dirty === true) .map(key => { return { control: key, value: info.co ...

Encountering problem with '@datadog/browser-rum' compilation related to the 'allowedTracingOrigins' attribute

I'm facing a typing problem with the @datadog/browser-rum library: Error: node_modules/@datadog/browser-rum-core/src/domain/configuration.ts:100:3 error TS2322: Type '{ applicationId: string; version: string; actionNameAttribute: string; premium ...

Dealing with CORS challenges in Angular 2 when trying to fulfill a promise

While attempting a service call in Angular, I encountered an error message: XMLHttpRequest cannot load http://geo.groupkt.com/ip/172.217.3.14/json. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http:/ ...

I am eager to incorporate the Twilio API into my project, however, I am encountering an error when trying to import Twilio into my TypeScript file

I am currently integrating the Twilio API into my project, but I'm encountering difficulties importing it into my TypeScript file. Interestingly, when I use the API in a JavaScript file, everything works smoothly without any issues. Below are the err ...

Having difficulty implementing Bootstrap on a demo Angular project

I am currently working on an Angular Application and facing issues with loading styles properly. Below is the code I have: menubar.html: <header> <nav class="navbar navbar-expand-lg navbar-dark bg-dark" style="display: inline&q ...