mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 09:13:33 +00:00
[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
This commit is contained in:
103
libs/components/src/tooltip/tooltip.spec.ts
Normal file
103
libs/components/src/tooltip/tooltip.spec.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user