// BlockTextEditor is the rebuild's schema-driven inline editor: it loads // the live block's raw markup, mounts a Gutenberg BlockEditor inside a // sibling DOM host, and on save serializes back, calls the save API, // splices the rendered HTML into the page, pushes an undo entry, and // fires an insights event. These tests pin those contracts plus the // keyboard surface (Cmd/Ctrl+Enter saves, Escape cancels) and the // load / save sad paths. import { act, fireEvent, render, waitFor } from '@testing-library/react'; const mockSave = jest.fn(); const mockGetBlockSource = jest.fn(); const mockInvalidateBlockSource = jest.fn(); const mockSplice = jest.fn(); const mockTrack = jest.fn(); const mockFetchLinkSuggestions = jest.fn(); const mockPushUndo = jest.fn(); const mockClearSelected = jest.fn(); const mockAskAiAboutElement = jest.fn(); const mockIsAgentAvailable = jest.fn(() => false); const mockIsAgentEligibleForTarget = jest.fn(() => true); const mockResetBlocks = jest.fn(); const mockClearSelectedBlock = jest.fn(); const mockResetSelection = jest.fn(); const mockSelectBlock = jest.fn(); const mockSelectionChange = jest.fn(); // Drives AutoSelectFirstBlock's useSelect; null → the editor reports an empty // block order so AutoSelectFirstBlock no-ops. let mockFirstBlock = null; let capturedProviderProps = null; jest.mock('@quick-edit/lib/api', () => ({ save: (...args) => mockSave(...args), })); jest.mock('@quick-edit/lib/block-source-cache', () => ({ getBlockSource: (...args) => mockGetBlockSource(...args), invalidateBlockSource: (...args) => mockInvalidateBlockSource(...args), })); jest.mock('@quick-edit/lib/dom', () => ({ splice: (...args) => mockSplice(...args), })); jest.mock('@quick-edit/lib/insights', () => ({ track: (...args) => mockTrack(...args), })); jest.mock('@quick-edit/lib/link-suggestions', () => ({ fetchLinkSuggestions: (...args) => mockFetchLinkSuggestions(...args), })); jest.mock('@quick-edit/state/store', () => ({ useQuickEditStore: (selector) => selector({ clearSelected: mockClearSelected }), })); jest.mock('@quick-edit/lib/ask-ai', () => ({ askAiAboutElement: (...args) => mockAskAiAboutElement(...args), isAgentAvailable: () => mockIsAgentAvailable(), })); jest.mock('@quick-edit/lib/agent-gate', () => ({ isAgentEligibleForTarget: (...args) => mockIsAgentEligibleForTarget(...args), })); jest.mock('@quick-edit/state/undo', () => ({ pushUndo: (...args) => mockPushUndo(...args), })); jest.mock('@quick-edit/components/toolbar/ColorButton', () => ({ ColorButton: ({ kind, label }) => ( ), })); jest.mock('@quick-edit/components/toolbar/HeadingLevelButton', () => ({ HeadingLevelButton: () => (