mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 22:03:36 +00:00
* 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
104 lines
3.3 KiB
TypeScript
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);
|
|
});
|
|
});
|