How do I test if a matTooltip is properly disabled in Angular Material?
Asked Answered
M

2

6

I've got a loop creating several matCard elements. These represent events. Some of them are in the past. I give these a class to grey them out, and add a matTooltip to explain what that means.

<mat-card
  class="event-card"
  *ngFor="let event of events"
  [class.past-event]="event.alreadyHappened()"
  matTooltip="This event has already happened"
  [matTooltipDisabled]="event.alreadyHappened() === false"
>
  <mat-card-header>...</mat-card-header>
  <mat-card-content></mat-card-content>
</mat-card>

The alreadyHappened() method returns a boolean.

I would like to test that the disabled property is set correctly, but I can't find how to check that in the matTooltip documentation.

I've got two tooltip harnesses for two cards. I can confirm that they're attached to the right card.

it('should display tootltip on past events', async () => {
  const tooltips = await loader.getAllHarnesses(MatTooltipHarness);
  expect(tooltips.length).toBe(2);

  expect(
    await (await tooltips[0].host()).hasClass('past-event')
  ).toBeTrue();
  expect(
    await (await tooltips[1].host()).hasClass('past-event')
  ).toBeFalse();

  await tooltips[0].show();
  expect(await tooltips[0].getTooltipText()).toEqual(
    'This event has already happened'
  );
);

What I don't understand is how to get the disabled property. I found the tests for the actual matTooltip class, but I think I shouldn't be messing with internals.

I've figured out that I can get component instances for children with this answer.

const ttFixture = fixture.debugElement.queryAll(By.directive(MatTooltip));
console.log(ttFixture);

But this gives me two mat-card elements, not the tooltips.

Do I need to create a fixture for the tooltip, or is there something else I am missing?

Mazurek answered 28/3, 2021 at 20:29 Comment(0)
M
9

Sometimes you just have to read the source. I ended up using what they do in the tests for matTooltip.

We need to import By to get a predicate, and the MatTooltip.

import { By } from '@angular/platform-browser'; 
import { MatTooltipModule, MatTooltip } from '@angular/material/tooltip';

We then need to import the MatTooltipModule into the TestBed. We also need animations to make the tooltip pop up.

TestBed.configureTestingModule({
  declarations: [EventsComponent],
   //                       VVVVVVVVVVVVVVVV
   imports: [MatCardModule, MatTooltipModule, NoopAnimationsModule],
   ...

And then we can use its injector to grab the component instances, which have properties.

    it('should display tootltip on past events', async () => {
      const ttDebugElements = fixture.debugElement.queryAll(By.css('.event-card'));
      const pastEventTooltip = ttDebugElements[0].injector.get<MatTooltip>(MatTooltip);
      const futureEventTooltip = ttDebugElements[1].injector.get<MatTooltip>(MatTooltip);

      expect(pastEventTooltip.disabled).toBeFalse();
      expect(futureEventTooltip.disabled).toBeTrue();
    });

This works like a charm.

Mazurek answered 29/3, 2021 at 11:25 Comment(0)
T
1

For anyone still asking this question, they've since added this in material version 16.1.0

Issue: https://github.com/angular/components/pull/27038
Changelog: https://github.com/angular/components/blob/main/CHANGELOG.md#16.1.0
Docs: https://material.angular.io/components/tooltip/api#MatTooltipHarness

Tropo answered 8/4 at 12:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.