From dee1712ef8eab4920d424cb91ea0edcd38cb05db Mon Sep 17 00:00:00 2001 From: Subhooo5 Date: Thu, 4 Jun 2026 01:07:30 +0530 Subject: [PATCH] =?UTF-8?q?test:=20ShareSheet=20mouse=20interactivity=20?= =?UTF-8?q?=E2=80=94=20hover,=20click=20propagation=20and=20touch=20events?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ShareSheet.mouse-interactivity.test.tsx | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 components/dashboard/ShareSheet.mouse-interactivity.test.tsx diff --git a/components/dashboard/ShareSheet.mouse-interactivity.test.tsx b/components/dashboard/ShareSheet.mouse-interactivity.test.tsx new file mode 100644 index 000000000..b4f9cc65d --- /dev/null +++ b/components/dashboard/ShareSheet.mouse-interactivity.test.tsx @@ -0,0 +1,118 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { render, screen, fireEvent } from '@testing-library/react'; +import ShareSheet from './ShareSheet'; +import type { DashboardExportData } from '@/types/dashboard'; + +vi.mock('framer-motion', () => ({ + motion: { + div: ({ children, ...props }: React.HTMLAttributes) => ( +
{children}
+ ), + }, + AnimatePresence: ({ children }: { children: React.ReactNode }) => <>{children}, +})); + +vi.mock('react-qr-code', () => ({ + default: ({ value }: { value: string }) => , +})); + +const mockHandleTwitter = vi.fn(); +const mockHandleLinkedIn = vi.fn(); +const mockHandleReddit = vi.fn(); +const mockHandleNativeShare = vi.fn(); + +vi.mock('@/hooks/useShareActions', () => ({ + useShareActions: () => ({ + states: {}, + handleTwitter: mockHandleTwitter, + handleLinkedIn: mockHandleLinkedIn, + handleReddit: mockHandleReddit, + handleDownloadPNG: vi.fn(), + handleDownloadWEBP: vi.fn(), + handleDownloadSVG: vi.fn(), + handleCopyMarkdown: vi.fn(), + handleDownloadJSON: vi.fn(), + handleNativeShare: mockHandleNativeShare, + }), +})); + +const mockExportData: DashboardExportData = { + stats: { currentStreak: 5, peakStreak: 10, totalContributions: 100 }, + languages: [], + activity: [], +}; + +const onClose = vi.fn(); + +const defaultProps = { + username: 'octocat', + isOpen: true, + onClose, + exportData: mockExportData, +}; + +describe('ShareSheet — Interactive Tooltips, Cursor Hovers & Touch Event Propagation', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('clicking the backdrop overlay propagates the click event to onClose', () => { + const { container } = render(); + + const overlay = container.querySelector('.fixed'); + expect(overlay).not.toBeNull(); + + fireEvent.click(overlay!); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + + it('clicking inside the modal panel stops propagation and does not call onClose', () => { + const { container } = render(); + + const modal = container.querySelector('[class*="max-w-"]'); + expect(modal).not.toBeNull(); + + fireEvent.click(modal!); + + expect(onClose).not.toHaveBeenCalled(); + }); + + it('mouseEnter on the QR group renders hover overlay action buttons in the DOM', () => { + const { container } = render(); + + const qrGroup = container.querySelector('.group'); + expect(qrGroup).not.toBeNull(); + + fireEvent.mouseEnter(qrGroup!); + + expect(screen.getByText('Copy Image')).toBeTruthy(); + expect(screen.getByText('Save File')).toBeTruthy(); + }); + + it('mouseleave on the QR group leaves the hover overlay in its opacity-0 hidden state', () => { + const { container } = render(); + + const qrGroup = container.querySelector('.group'); + expect(qrGroup).not.toBeNull(); + + const hoverOverlay = qrGroup!.querySelector('.opacity-0'); + expect(hoverOverlay).not.toBeNull(); + + fireEvent.mouseLeave(qrGroup!); + + expect(hoverOverlay!.classList.contains('opacity-0')).toBe(true); + }); + + it('touch events on the Share on X button do not block the click handler from firing', () => { + render(); + + const xButton = screen.getByRole('button', { name: /share on x/i }); + + fireEvent.touchStart(xButton); + fireEvent.touchEnd(xButton); + fireEvent.click(xButton); + + expect(mockHandleTwitter).toHaveBeenCalledTimes(1); + }); +});