Files
Psychotoxical-psysonic/src/components/TooltipPortal.test.tsx
T
cucadmuh ae9be74719 feat(settings): compact server cards with capability badges (#1054)
* feat(settings): redesign server cards with identity line and capability badges

Compact two-line server headers (entry name + user@host), HTTPS lock, and a
clickable version info tooltip. Navidrome ≥0.62 shows a green AudioMuse inline
badge; older Navidrome keeps the manual toggle row. Adds click-pinned tooltips
via data-tooltip-click on TooltipPortal.

* feat(settings): unify use/active slot and move delete into edit form

Merge Active badge and Use button into one rightmost action; Active uses
green styling. Reorder actions to edit, test, use/active. Remove the card
delete icon — deletion lives in the server edit form footer.

* docs: note compact server cards in CHANGELOG and credits (PR #1054)

* fix(credits): move PR #1054 server cards line to cucadmuh block

Was appended to Psychotoxical's contributions array by mistake; CHANGELOG
already credited cucadmuh (gh pr view author).
2026-06-10 00:25:30 +03:00

131 lines
3.6 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { act, fireEvent, screen } from '@testing-library/react';
import { renderWithProviders } from '@/test/helpers/renderWithProviders';
import TooltipPortal from './TooltipPortal';
function Fixture() {
return (
<>
<TooltipPortal />
<button data-tooltip="Play this album">play</button>
</>
);
}
describe('TooltipPortal open delay', () => {
beforeEach(() => vi.useFakeTimers());
afterEach(() => {
vi.runOnlyPendingTimers();
vi.useRealTimers();
});
it('shows the tooltip only after the 1s open delay', () => {
renderWithProviders(<Fixture />);
const btn = screen.getByText('play');
fireEvent.mouseOver(btn);
expect(screen.queryByText('Play this album')).toBeNull();
act(() => {
vi.advanceTimersByTime(999);
});
expect(screen.queryByText('Play this album')).toBeNull();
act(() => {
vi.advanceTimersByTime(1);
});
expect(screen.getByText('Play this album')).toBeInTheDocument();
});
it('cancels the pending tooltip when the pointer leaves before the delay', () => {
renderWithProviders(<Fixture />);
const btn = screen.getByText('play');
fireEvent.mouseOver(btn);
act(() => {
vi.advanceTimersByTime(500);
});
fireEvent.mouseOut(btn, { relatedTarget: document.body });
act(() => {
vi.advanceTimersByTime(1000);
});
expect(screen.queryByText('Play this album')).toBeNull();
});
it('hides immediately on mousedown', () => {
renderWithProviders(<Fixture />);
const btn = screen.getByText('play');
fireEvent.mouseOver(btn);
act(() => {
vi.advanceTimersByTime(1000);
});
expect(screen.getByText('Play this album')).toBeInTheDocument();
fireEvent.mouseDown(btn);
expect(screen.queryByText('Play this album')).toBeNull();
});
it('shows immediately on click when data-tooltip-click is set', () => {
renderWithProviders(
<>
<TooltipPortal />
<button data-tooltip="Server version" data-tooltip-click="">info</button>
</>,
);
const btn = screen.getByText('info');
fireEvent.click(btn);
expect(screen.getByText('Server version')).toBeInTheDocument();
});
it('does not hide click-mode tooltips on mousedown', () => {
renderWithProviders(
<>
<TooltipPortal />
<button data-tooltip="Server version" data-tooltip-click="">info</button>
</>,
);
const btn = screen.getByText('info');
fireEvent.click(btn);
expect(screen.getByText('Server version')).toBeInTheDocument();
fireEvent.mouseDown(btn);
expect(screen.getByText('Server version')).toBeInTheDocument();
});
it('toggles off when the click anchor is clicked again', () => {
renderWithProviders(
<>
<TooltipPortal />
<button data-tooltip="Server version" data-tooltip-click="">info</button>
</>,
);
const btn = screen.getByText('info');
fireEvent.click(btn);
expect(screen.getByText('Server version')).toBeInTheDocument();
fireEvent.click(btn);
expect(screen.queryByText('Server version')).toBeNull();
});
it('keeps click-opened tooltips visible after mouseout', () => {
renderWithProviders(
<>
<TooltipPortal />
<button data-tooltip="Server version" data-tooltip-click="">info</button>
</>,
);
const btn = screen.getByText('info');
fireEvent.click(btn);
expect(screen.getByText('Server version')).toBeInTheDocument();
fireEvent.mouseOut(btn, { relatedTarget: document.body });
expect(screen.getByText('Server version')).toBeInTheDocument();
});
});