1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-11 22:03:36 +00:00
Files
browser/libs/components/src/tooltip/tooltip.spec.ts
Bryan Cunningham 08a022fa52 [CL-227] Tooltip component (#16442)
* add tooltip component

* fix typescript errors

* fix more typescript errors

* remove css comments

* fix tooltip blocking mouse events

* move default position logic to shared util

* fix tooltip stories options

* add tooltip spec

* add offset arg to default positions

* add shadow to tooltip

* increase offset

* adding max width

* fix disabled button cursor

* add stronger position type

* fixing types

* change get positions function to type return correctly

* more fixing types

* default options object

* add mock to tooltip stories

* add figma link to story

* update positions file name. remove getter

* remove standalone. add comment about component use

* add jsdoc comment to directive inputs

* fix typo

* remove instances of setInput

* fix storybook injection error

* remove unneeded functions

* remove unneeded variables

* remove comment

* move popover positions back with component

* fix popover i18n mock

* creat etooltip positions file

* update test to account for change to setInput calls

* remove panel class as it's not necessary

* improve tooltip docs page

* use classes for styling. Simpliy position changes

* simplify tests. No longer need to track position changes

* move comment to correct place

* fix typos

* remove unnecessary standalone declaration
2025-10-01 14:01:53 -04:00

104 lines
3.3 KiB
TypeScript

import {
ConnectedOverlayPositionChange,
ConnectionPositionPair,
OverlayConfig,
Overlay,
} from "@angular/cdk/overlay";
import { ComponentPortal } from "@angular/cdk/portal";
import { Component } from "@angular/core";
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { By } from "@angular/platform-browser";
import { Observable, Subject } from "rxjs";
import { TooltipDirective } from "./tooltip.directive";
@Component({
standalone: true,
imports: [TooltipDirective],
template: ` <button [bitTooltip]="tooltipText" type="button">Hover or focus me</button> `,
})
class TooltipHostComponent {
tooltipText = "Hello Tooltip";
}
/** Minimal strategy shape the directive expects */
interface StrategyLike {
withFlexibleDimensions: (flex: boolean) => StrategyLike;
withPush: (push: boolean) => StrategyLike;
withPositions: (positions: ReadonlyArray<ConnectionPositionPair>) => StrategyLike;
readonly positionChanges: Observable<ConnectedOverlayPositionChange>;
}
/** Minimal Overlay service shape */
interface OverlayLike {
position: () => { flexibleConnectedTo: (_: unknown) => StrategyLike };
create: (_: OverlayConfig) => OverlayRefStub;
scrollStrategies: { reposition: () => unknown };
}
interface OverlayRefStub {
attach: (portal: ComponentPortal<unknown>) => unknown;
updatePosition: () => void;
}
describe("TooltipDirective (visibility only)", () => {
let fixture: ComponentFixture<TooltipHostComponent>;
beforeEach(() => {
const positionChanges$ = new Subject<ConnectedOverlayPositionChange>();
const strategy: StrategyLike = {
withFlexibleDimensions: jest.fn(() => strategy),
withPush: jest.fn(() => strategy),
withPositions: jest.fn(() => strategy),
get positionChanges() {
return positionChanges$.asObservable();
},
};
const overlayRefStub: OverlayRefStub = {
attach: jest.fn(() => ({})),
updatePosition: jest.fn(),
};
const overlayMock: OverlayLike = {
position: () => ({ flexibleConnectedTo: () => strategy }),
create: (_: OverlayConfig) => overlayRefStub,
scrollStrategies: { reposition: () => ({}) },
};
TestBed.configureTestingModule({
imports: [TooltipHostComponent],
providers: [{ provide: Overlay, useValue: overlayMock as unknown as Overlay }],
});
fixture = TestBed.createComponent(TooltipHostComponent);
fixture.detectChanges();
});
function getDirective(): TooltipDirective {
const hostDE = fixture.debugElement.query(By.directive(TooltipDirective));
return hostDE.injector.get(TooltipDirective);
}
it("sets isVisible to true on mouseenter", () => {
const button: HTMLButtonElement = fixture.debugElement.query(By.css("button")).nativeElement;
const directive = getDirective();
const isVisible = (directive as unknown as { isVisible: () => boolean }).isVisible;
button.dispatchEvent(new Event("mouseenter"));
expect(isVisible()).toBe(true);
});
it("sets isVisible to true on focus", () => {
const button: HTMLButtonElement = fixture.debugElement.query(By.css("button")).nativeElement;
const directive = getDirective();
const isVisible = (directive as unknown as { isVisible: () => boolean }).isVisible;
button.dispatchEvent(new Event("focus"));
expect(isVisible()).toBe(true);
});
});