mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 00:12:39 +00:00
fix: stop the React warning about isPressed on every Contacts visit
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { render, screen, fireEvent, act } from '@testing-library/react';
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { ContactListItem } from '../contact-list-item';
|
||||
import type { ContactCard } from '@/lib/jmap/types';
|
||||
@@ -82,4 +82,24 @@ describe('ContactListItem', () => {
|
||||
const { container } = render(<ContactListItem contact={contact} {...baseProps} density="extra-compact" />);
|
||||
expect(container.querySelector('[data-testid="avatar"]') || container.querySelector('.rounded-full')).toBeNull();
|
||||
});
|
||||
|
||||
it('opens the row menu on long-press without leaking the press state onto the row', () => {
|
||||
const errors = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
vi.useFakeTimers();
|
||||
try {
|
||||
const onLongPress = vi.fn();
|
||||
const { container } = render(<ContactListItem contact={contact} {...baseProps} onLongPress={onLongPress} />);
|
||||
const row = container.firstElementChild!;
|
||||
const touchStart = new Event('touchstart', { bubbles: true });
|
||||
Object.defineProperty(touchStart, 'touches', { value: [{ clientX: 5, clientY: 5 }] });
|
||||
act(() => { row.dispatchEvent(touchStart); });
|
||||
act(() => { vi.advanceTimersByTime(600); });
|
||||
expect(onLongPress).toHaveBeenCalledWith(row);
|
||||
const unknownProp = errors.mock.calls.some((args) => args.some((a) => String(a).includes('isPressed')));
|
||||
expect(unknownProp).toBe(false);
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
errors.mockRestore();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -38,6 +38,20 @@ function renderSidebar(onComposeGroup = vi.fn()) {
|
||||
return onComposeGroup;
|
||||
}
|
||||
|
||||
// First in the file: React warns about an unknown DOM prop only once per run.
|
||||
describe('ContactsSidebar — row props', () => {
|
||||
it('keeps the long-press state off the row element', () => {
|
||||
const errors = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
try {
|
||||
renderSidebar();
|
||||
const unknownProp = errors.mock.calls.some((args) => args.some((a) => String(a).includes('isPressed')));
|
||||
expect(unknownProp).toBe(false);
|
||||
} finally {
|
||||
errors.mockRestore();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('ContactsSidebar — compose to group', () => {
|
||||
beforeEach(() => vi.clearAllMocks());
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ export function ContactListItem({ contact, isSelected, isChecked, hasSelection,
|
||||
return (
|
||||
<div
|
||||
ref={rowRef}
|
||||
{...(onLongPress ? longPress : {})}
|
||||
{...(onLongPress ? longPress.handlers : {})}
|
||||
role="option"
|
||||
aria-selected={isSelected || isChecked}
|
||||
tabIndex={isFocused ? 0 : -1}
|
||||
|
||||
@@ -788,7 +788,7 @@ function SidebarRow({
|
||||
ref={rowRef}
|
||||
{...rowProps}
|
||||
{...dropProps}
|
||||
{...(onOpenMenu ? longPress : {})}
|
||||
{...(onOpenMenu ? longPress.handlers : {})}
|
||||
onContextMenu={onContextMenu}
|
||||
className={cn(
|
||||
// 32px rows, 44px on touch (R1).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
import { useCallback, useMemo, useRef, useState } from "react";
|
||||
|
||||
const LONG_PRESS_DURATION = 500;
|
||||
const MOVE_THRESHOLD = 10;
|
||||
@@ -69,5 +69,12 @@ export function useLongPress(
|
||||
firedRef.current = false;
|
||||
}, [cancel]);
|
||||
|
||||
return { onTouchStart, onTouchEnd, onTouchMove, onTouchCancel, isPressed };
|
||||
// `handlers` holds only the touch handlers, safe to spread onto a DOM
|
||||
// element; spreading the whole result would put `isPressed` on it.
|
||||
const handlers = useMemo(
|
||||
() => ({ onTouchStart, onTouchEnd, onTouchMove, onTouchCancel }),
|
||||
[onTouchStart, onTouchEnd, onTouchMove, onTouchCancel]
|
||||
);
|
||||
|
||||
return { onTouchStart, onTouchEnd, onTouchMove, onTouchCancel, isPressed, handlers };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user