From d32e904a9d4ea1517b596134b739c59c553b3583 Mon Sep 17 00:00:00 2001 From: Carlos Emiliano Castro Trejo <102700317+ccastrotrejo@users.noreply.github.com> Date: Mon, 27 Jan 2025 09:26:49 -0800 Subject: [PATCH] fix(designer): Render copied tooltip properly (#6463) * Update component to render properly * Add unit tests * Update unit tests * Update e2e tests * update unit tests --- e2e/designer/mock-copypastescope.spec.ts | 2 + .../lib/ui/CustomNodes/OperationCardNode.tsx | 2 +- .../src/lib/ui/CustomNodes/ScopeCardNode.tsx | 2 +- .../DesignerContextualMenu/CopyTooltip.tsx | 36 ++++---- .../DesignerContextualMenu.tsx | 2 +- .../__test__/CopyTooltip.spec.tsx | 86 +++++++++++++++++++ .../__snapshots__/CopyTooltip.spec.tsx.snap | 67 +++++++++++++++ 7 files changed, 176 insertions(+), 21 deletions(-) create mode 100644 libs/designer/src/lib/ui/common/DesignerContextualMenu/__test__/CopyTooltip.spec.tsx create mode 100644 libs/designer/src/lib/ui/common/DesignerContextualMenu/__test__/__snapshots__/CopyTooltip.spec.tsx.snap diff --git a/e2e/designer/mock-copypastescope.spec.ts b/e2e/designer/mock-copypastescope.spec.ts index f21660b1d74..1ada7b65d00 100644 --- a/e2e/designer/mock-copypastescope.spec.ts +++ b/e2e/designer/mock-copypastescope.spec.ts @@ -15,6 +15,8 @@ test( }); await page.getByTestId('msla-copy-menu-option').click(); + await expect(page.getByRole('tooltip', { name: 'Copied!' })).toBeVisible(); + await expect(page.getByTestId('msla-tooltip-location-condition')).toBeVisible(); await page.getByTestId('msla-plus-button-initialize_variable-condition').click(); await page.getByTestId('msla-paste-button-initialize_variable-condition').click(); await page.waitForTimeout(1000); diff --git a/libs/designer/src/lib/ui/CustomNodes/OperationCardNode.tsx b/libs/designer/src/lib/ui/CustomNodes/OperationCardNode.tsx index f9af181986c..5ce7a74dab3 100644 --- a/libs/designer/src/lib/ui/CustomNodes/OperationCardNode.tsx +++ b/libs/designer/src/lib/ui/CustomNodes/OperationCardNode.tsx @@ -336,7 +336,7 @@ const DefaultNode = ({ targetPosition = Position.Top, sourcePosition = Position. isLoadingDynamicData={isLoadingDynamicData} nodeIndex={nodeIndex} /> - {showCopyCallout ? : null} + {showCopyCallout ? : null} {showLeafComponents ? ( diff --git a/libs/designer/src/lib/ui/CustomNodes/ScopeCardNode.tsx b/libs/designer/src/lib/ui/CustomNodes/ScopeCardNode.tsx index 04d051db7cf..a46c97f7f5b 100644 --- a/libs/designer/src/lib/ui/CustomNodes/ScopeCardNode.tsx +++ b/libs/designer/src/lib/ui/CustomNodes/ScopeCardNode.tsx @@ -334,7 +334,7 @@ const ScopeCardNode = ({ data, targetPosition = Position.Top, sourcePosition = P setFocus={shouldFocus} nodeIndex={nodeIndex} /> - {showCopyCallout ? : null} + {showCopyCallout ? : null} {normalizedType === constants.NODE.TYPE.FOREACH && isMonitoringView ? renderLoopsPager : null} diff --git a/libs/designer/src/lib/ui/common/DesignerContextualMenu/CopyTooltip.tsx b/libs/designer/src/lib/ui/common/DesignerContextualMenu/CopyTooltip.tsx index 23b7fef04e9..3f0fb5645b2 100644 --- a/libs/designer/src/lib/ui/common/DesignerContextualMenu/CopyTooltip.tsx +++ b/libs/designer/src/lib/ui/common/DesignerContextualMenu/CopyTooltip.tsx @@ -1,16 +1,17 @@ -/* eslint-disable react/display-name */ import { Tooltip } from '@fluentui/react-components'; +import { replaceWhiteSpaceWithUnderscore } from '@microsoft/logic-apps-shared'; import { useOnViewportChange } from '@xyflow/react'; -import { useMemo, useRef } from 'react'; +import { useRef } from 'react'; import { useIntl } from 'react-intl'; export interface CopyTooltipProps { targetRef?: React.RefObject; location?: { x: number; y: number }; hideTooltip: () => void; + id: string; } -export const CopyTooltip = ({ targetRef: ref, location, hideTooltip }: CopyTooltipProps) => { +export const CopyTooltip = ({ targetRef: ref, location, hideTooltip, id }: CopyTooltipProps) => { useOnViewportChange({ onStart: () => hideTooltip() }); const intl = useIntl(); @@ -22,21 +23,20 @@ export const CopyTooltip = ({ targetRef: ref, location, hideTooltip }: CopyToolt const locationRef = useRef(null); - const TooltipComponent = useMemo( - () => () => ( - - ), - [copiedText, ref] - ); - return ( -
- -
+ +
+ ); }; diff --git a/libs/designer/src/lib/ui/common/DesignerContextualMenu/DesignerContextualMenu.tsx b/libs/designer/src/lib/ui/common/DesignerContextualMenu/DesignerContextualMenu.tsx index 5760ab6e350..e5c0d3b4706 100644 --- a/libs/designer/src/lib/ui/common/DesignerContextualMenu/DesignerContextualMenu.tsx +++ b/libs/designer/src/lib/ui/common/DesignerContextualMenu/DesignerContextualMenu.tsx @@ -185,7 +185,7 @@ export const DesignerContextualMenu = () => { title={title} setOpen={(o) => setOpen(o)} /> - {showCopyCallout ? : null} + {showCopyCallout ? : null} ); }; diff --git a/libs/designer/src/lib/ui/common/DesignerContextualMenu/__test__/CopyTooltip.spec.tsx b/libs/designer/src/lib/ui/common/DesignerContextualMenu/__test__/CopyTooltip.spec.tsx new file mode 100644 index 00000000000..2aeb794787f --- /dev/null +++ b/libs/designer/src/lib/ui/common/DesignerContextualMenu/__test__/CopyTooltip.spec.tsx @@ -0,0 +1,86 @@ +import { render, screen } from '@testing-library/react'; +import { CopyTooltip, CopyTooltipProps } from '../CopyTooltip'; +import { describe, it, expect, vi, afterEach, beforeAll } from 'vitest'; +import React from 'react'; + +const hideTooltipMock = vi.fn(); + +vi.mock('@xyflow/react', async () => { + const actualIntl = await vi.importActual('@xyflow/react'); + return { + ...actualIntl, + useOnViewportChange: vi.fn(() => ({ onStart: hideTooltipMock })), + }; +}); + +vi.mock('react-intl', async () => { + const actualIntl = await vi.importActual('react-intl'); + return { + ...actualIntl, + useIntl: () => ({ + formatMessage: vi.fn(() => 'Copied!'), + }), + }; +}); + +describe('CopyTooltip', () => { + beforeAll(() => { + const portalRoot = document.createElement('div'); + portalRoot.setAttribute('id', 'root'); + document.body.appendChild(portalRoot); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + const renderComponent = (props: Partial = {}) => { + const defaultProps: CopyTooltipProps = { + hideTooltip: hideTooltipMock, + id: 'test-id', + ...props, + }; + + return render(); + }; + + it('should render the tooltip with the correct content', () => { + const copiedText = 'Copied!'; + const location = { x: 100, y: 100 }; + + // Render the Tooltip component + const { baseElement } = renderComponent({ location }); + + // Get the tooltip div and the location div + const tooltipDiv = screen.getByRole('tooltip'); + const tooltipLocationDiv = screen.getByTestId('msla-tooltip-location-test_id'); + + // Assert that the tooltip and location div are rendered correctly + expect(tooltipDiv).toBeInTheDocument(); + expect(screen.getByText(copiedText)).toBeVisible(); + expect(tooltipLocationDiv).toBeInTheDocument(); + expect(baseElement).toMatchSnapshot(); + }); + + it('should position the tooltip based on the provided location', () => { + const location = { x: 100, y: 100 }; + + // Render the Tooltip component + const { baseElement } = renderComponent({ location }); + + // Get the tooltip location div + const tooltipLocationDiv = screen.getByTestId('msla-tooltip-location-test_id'); + + // Assert that the location div are rendered correctly + expect(tooltipLocationDiv).toBeInTheDocument(); + expect(tooltipLocationDiv).toHaveStyle({ position: 'absolute', top: '100px', left: '100px' }); + expect(baseElement).toMatchSnapshot(); + }); + + it('should default to locationRef if targetRef is not provided', () => { + renderComponent(); + + const tooltipDiv = screen.getByRole('tooltip').parentElement; + expect(tooltipDiv).toHaveStyle({ position: 'absolute', top: '0px', left: '0px' }); + }); +}); diff --git a/libs/designer/src/lib/ui/common/DesignerContextualMenu/__test__/__snapshots__/CopyTooltip.spec.tsx.snap b/libs/designer/src/lib/ui/common/DesignerContextualMenu/__test__/__snapshots__/CopyTooltip.spec.tsx.snap new file mode 100644 index 00000000000..ba540f376e5 --- /dev/null +++ b/libs/designer/src/lib/ui/common/DesignerContextualMenu/__test__/__snapshots__/CopyTooltip.spec.tsx.snap @@ -0,0 +1,67 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`CopyTooltip > should position the tooltip based on the provided location 1`] = ` + +
+
+
+
+
+ +
+ +`; + +exports[`CopyTooltip > should render the tooltip with the correct content 1`] = ` + +
+
+
+
+
+ +
+ +`;