NativeElement properties scrollWith and clientWidth always zero in specs

112 Views Asked by At

The following code produces the desired results when being used, however, I'm failing to test it.

import { AfterContentInit, Directive, ElementRef, HostListener } from '@angular/core';
import { MatTooltip } from '@angular/material/tooltip';

@Directive({
  standalone: true,
  selector: '[matTooltip][appShowTooltipIfTruncated]'
})
export class ShowTooltipIfTruncatedDirective implements AfterContentInit {
  constructor(
    private readonly matTooltip: MatTooltip,
    private readonly elementRef: ElementRef<HTMLElement>
  ) { }

  @HostListener ('window: resize', ['Sevent'])
  onResize(): void {
    this.toggleTooltipStatus();
  }

  public ngAfterContentInit(): void {
    this.toggleTooltipStatus();
  }

  private toggleTooltipStatus(): void {
    const element = this.elementRef.nativeElement;
    this.matTooltip.disabled = element.scrollWidth <= element.clientWidth;
  }
}

I would like to perform the following tests:

  1. When the directive is initialised, if the scrollwidth is greater than the clientwidth the matTooltip.disabled is true;
  2. When the directive is initialised, if the scrollwidth is lesser than the clientwidth the matTooltip.disabled is false;
  3. After initialisation, if a window resize event is fired, it trigger a change in the matTooltip.disabled property.

Working on project with Angular 16 and using jest to perform the tests. Currently trying to test a directive but it seems that no matter what, the NativeElement properties scrollwidth and clientwidth of the ElementRef are always at 0.

  • I tried providing an object that replaces the ElementRef that is injected in the directive, but it seems this is not passed into the directive when the code is ran. Would also like to understand why I'm unable to provide an instance that replaces the ElementRef.
  • Also tried manually triggering the changeDetection, but it does not make any difference, the values returned by scrollwidth and clientwidth are still 0.
  • Tried to add some css to counter the display inline issue, but also did not produce any results.

Please find below an example of my specs:

import { Component } from "@angular/core";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { ShowTooltipIfTruncatedDirective } from "./show-if-truncated.directive";
import { By } from "@angular/platform-browser";
import { MatTooltip, MatTooltipModule } from "@angular/material/tooltip";

@Component({
  template: `
    <div style="width: 200px; heigh=200px; display=block">
      <div style="width: 100px" [matTooltip]="'tooltip text'" appShowTooltipIfTruncated>Test</div>  
    </div>
  `
})
class HostComponent {}

describe('ShowTooltipIfTruncatedDirective', () => {
  let fixture: ComponentFixture<HostComponent>;
  let directive: ShowTooltipIfTruncatedDirective;
  let matTooltip: MatTooltip;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [HostComponent],
      imports: [ShowTooltipIfTruncatedDirective, MatTooltipModule],
    }).compileComponents();

    fixture = TestBed.createComponent(HostComponent);
    fixture.detectChanges();
    directive = fixture.debugElement.query(By.directive(ShowTooltipIfTruncatedDirective)).componentInstance;
    matTooltip = fixture.debugElement.query(By.directive(MatTooltip)).componentInstance;
  });

  it('should create', () => {
    expect(directive).toBeTruthy();
  })
  it('should disable the tooltip on window width changes', () => {
    expect(matTooltip.disabled).toEqual(false);

    window.dispatchEvent(new Event('resize', { bubbles: true }))

    fixture.detectChanges();

    expect(matTooltip.disabled).toEqual(true);
  })
})
0

There are 0 best solutions below