diff --git a/packages/web/src/components/layout/DmMemberRow.test.tsx b/packages/web/src/components/layout/DmMemberRow.test.tsx new file mode 100644 index 00000000..1a0d12a5 --- /dev/null +++ b/packages/web/src/components/layout/DmMemberRow.test.tsx @@ -0,0 +1,227 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { render, screen, fireEvent, act } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import type { User } from '@backspace/shared'; + +// Stub AudioManager — pulled in transitively via spaceStore from useCanonicalUserView. +vi.mock('../../audio/AudioManager', () => ({ + AudioManager: { + getInstance: vi.fn().mockReturnValue({ + setOutputDevice: vi.fn(), + setVolume: vi.fn(), + }), + }, +})); + +// Force desktop rendering in ContextMenuRenderer (mobile path triggers +// document-level long-press listeners we don't need here). +vi.mock('../../stores/uiStore', () => ({ + useUIStore: (selector: (s: { isMobile: boolean; openUserProfile: () => void }) => unknown) => + selector({ isMobile: false, openUserProfile: () => {} }), +})); + +import { DmMemberRow, type DmMemberRowAction } from './DmMemberRow'; +import { ContextMenuRenderer } from '../ui/ContextMenuRenderer'; +import { useContextMenuStore } from '../../stores/contextMenuStore'; + +function makeUser(overrides: Partial = {}): User { + return { + id: 'u-1', + username: 'alice', + displayName: 'Alice', + avatar: null, + banner: null, + accentColor: null, + avatarColor: null, + bio: null, + status: 'online', + customStatus: null, + isAdmin: false, + createdAt: 0, + homeInstance: null, + homeUserId: null, + replicatedInstances: [], + ...overrides, + }; +} + +beforeEach(() => { + // Make sure each test starts with no menu open. + act(() => { + useContextMenuStore.getState().close(); + }); +}); + +function renderRow(props: Partial[0]> = {}) { + const onMenuAction = vi.fn<(action: DmMemberRowAction, member: User) => void>(); + const member = props.member ?? makeUser(); + const utils = render( + <> + + + , + ); + return { ...utils, onMenuAction, member }; +} + +function openMenuByContextMenu(target: HTMLElement) { + fireEvent.contextMenu(target, { clientX: 100, clientY: 100 }); +} + +function getMenuLabels(): string[] { + // Menu items render as + )} + + ); +}