import { cleanup, fireEvent, screen, waitFor } from '@testing-library/react'; import { afterEach, describe, expect, it, vi } from 'vitest'; import InlineTitleEditor from './InlineTitleEditor'; import { renderWithIntl } from '@/utils/test/renderWithIntl'; const mocks = vi.hoisted(() => ({ renameNote: vi.fn(), refresh: vi.fn(), })); vi.mock('next/navigation', () => ({ useRouter: () => ({ refresh: mocks.refresh }), })); describe('InlineTitleEditor', () => { afterEach(cleanup); it('renames on blur and refreshes; ignores empty titles', async () => { mocks.renameNote.mockResolvedValue(true); renderWithIntl(); const input = screen.getByLabelText('Title'); fireEvent.change(input, { target: { value: ' ' } }); fireEvent.blur(input); expect(mocks.renameNote).not.toHaveBeenCalled(); expect(input).toHaveValue('Old'); fireEvent.change(input, { target: { value: 'New' } }); fireEvent.blur(input); await waitFor(() => expect(mocks.renameNote).toHaveBeenCalledWith('New')); await waitFor(() => expect(mocks.refresh).toHaveBeenCalled()); }); it('restores the saved title when the rename rejects', async () => { mocks.renameNote.mockRejectedValue(new Error('network')); renderWithIntl(); const input = screen.getByLabelText('Title'); fireEvent.change(input, { target: { value: 'New' } }); fireEvent.blur(input); await waitFor(() => expect(input).toHaveValue('Old')); }); it('ignores Enter while an IME composition is active', () => { mocks.renameNote.mockResolvedValue(true); renderWithIntl(); const input = screen.getByLabelText('Title'); input.focus(); fireEvent.change(input, { target: { value: 'New' } }); fireEvent.keyDown(input, { key: 'Enter', isComposing: true }); expect(input).toHaveFocus(); expect(mocks.renameNote).not.toHaveBeenCalled(); }); it('does not save the canceled title on Escape', () => { renderWithIntl(); const input = screen.getByLabelText('Title'); input.focus(); fireEvent.change(input, { target: { value: 'New' } }); fireEvent.keyDown(input, { key: 'Escape' }); fireEvent.blur(input); expect(input).toHaveValue('Old'); expect(mocks.renameNote).not.toHaveBeenCalled(); }); });