type TooltipStoreInterface = { addTooltip(tooltip: React.Component): void; closeAllTooltips(): void; getOpenableSingleTooltips(): React.Component[]; init(): TooltipStoreInterface; openAllTooltips(): boolean; removeTooltip(tooltip: React.Component): void; tooltips: React.Component[]; }; const MAX_TOOLTIPS_TO_OPEN = 100; const TooltipStore: TooltipStoreInterface = { tooltips: [], getOpenableSingleTooltips() { return this.tooltips.filter(tooltip => { // Filtering out disabled tooltips and lists of tooltips (which cause rendering issues for snapshots) using the internal 'key' const _internals = (tooltip as any)._reactInternalFiber || (tooltip as any)._reactInternals; return ( !(tooltip.props as any).disabled && !_internals.key && !(tooltip.props as any).disableForVisualTest ); }); }, /** * Called via window.__openAllTooltips in selenium tests to check tooltip snapshots */ openAllTooltips() { const tooltips = this.getOpenableSingleTooltips(); if (!tooltips.length || tooltips.length > MAX_TOOLTIPS_TO_OPEN) { // Pages with too many tooltip components will take too long to render and it isn't likely helpful anyway. return false; } tooltips.forEach(tooltip => { tooltip.setState({ isOpen: true, usesGlobalPortal: false, }); }); return true; }, /** * Called via window.__closeAllTooltips in selenium tests to cleanup tooltips after taking a snapshot */ closeAllTooltips() { const tooltips = this.getOpenableSingleTooltips(); tooltips.forEach(tooltip => { tooltip.setState({ isOpen: false, usesGlobalPortal: true, }); }); }, init(): TooltipStoreInterface { window.__openAllTooltips = this.openAllTooltips.bind(this); window.__closeAllTooltips = this.closeAllTooltips.bind(this); return this; }, addTooltip(tooltip: React.Component) { this.tooltips.push(tooltip); }, removeTooltip(tooltip: React.Component) { this.tooltips = this.tooltips.filter(t => t !== tooltip); }, }; export default TooltipStore.init();