diff --git a/client/src/components/Chat/Input/__tests__/DuringRunSendButton.test.tsx b/client/src/components/Chat/Input/__tests__/DuringRunSendButton.test.tsx index 7e68c48f9f..c1fb830776 100644 --- a/client/src/components/Chat/Input/__tests__/DuringRunSendButton.test.tsx +++ b/client/src/components/Chat/Input/__tests__/DuringRunSendButton.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { useForm } from 'react-hook-form'; -import { render, screen, fireEvent, act } from '@testing-library/react'; +import { render, screen, fireEvent } from '@testing-library/react'; import type { SteeringControls } from '~/hooks/Chat/useSteering'; import DuringRunSendButton from '../DuringRunSendButton'; @@ -8,6 +8,17 @@ jest.mock('~/hooks', () => ({ useLocalize: () => (key: string) => key, })); +/** + * Renders the hovercard eagerly. Ariakit's real show path depends on pointer + * geometry, which jsdom reports as zeros — driving it from a test asserts + * Ariakit's hover behavior rather than which rows this component disables. + */ +jest.mock('@ariakit/react', () => ({ + HovercardProvider: ({ children }: { children: React.ReactNode }) =>
{children}
, + HovercardAnchor: ({ render }: { render: React.ReactElement }) => render, + Hovercard: ({ children }: { children: React.ReactNode }) =>
{children}
, +})); + const TEXT = 'stop, do not run that command'; const mockInterruptSteer = jest.fn(() => true); @@ -42,25 +53,13 @@ function Harness({ steering }: { steering: SteeringControls }) { ); } -/** The rows only mount once the hovercard clears its show delay. */ -async function openMenu(options: StubOptions) { +function openMenu(options: StubOptions) { render(); - const anchor = screen.getByTestId('during-run-send-button'); - fireEvent.mouseEnter(anchor); - fireEvent.mouseMove(anchor); - await act(async () => { - jest.advanceTimersByTime(500); - }); expect(screen.getByText('com_ui_interrupt_steer')).toBeInTheDocument(); } beforeEach(() => { jest.clearAllMocks(); - jest.useFakeTimers(); -}); - -afterEach(() => { - jest.useRealTimers(); }); describe('DuringRunSendButton — Interrupt & steer availability', () => { @@ -69,8 +68,8 @@ describe('DuringRunSendButton — Interrupt & steer availability', () => { * approval, so a live row would silently do nothing at exactly the moment a * user is trying to stop a tool call. */ - test('disables Interrupt & steer while the run is paused on tool approval', async () => { - await openMenu({ pausedOnApproval: true, canSteer: false }); + test('disables Interrupt & steer while the run is paused on tool approval', () => { + openMenu({ pausedOnApproval: true, canSteer: false }); const row = screen.getByText('com_ui_interrupt_steer').closest('button'); expect(row).toHaveAttribute('aria-disabled', 'true'); @@ -86,8 +85,8 @@ describe('DuringRunSendButton — Interrupt & steer availability', () => { * `interruptSteer` deliberately falls back to interrupt & send — disabling * the row there would make it dead for the whole first turn. */ - test('keeps Interrupt & steer live before a conversation exists', async () => { - await openMenu({ pausedOnApproval: false, canSteer: false }); + test('keeps Interrupt & steer live before a conversation exists', () => { + openMenu({ pausedOnApproval: false, canSteer: false }); const row = screen.getByText('com_ui_interrupt_steer').closest('button'); expect(row).toHaveAttribute('aria-disabled', 'false'); @@ -97,8 +96,8 @@ describe('DuringRunSendButton — Interrupt & steer availability', () => { expect(mockOnConsumed).toHaveBeenCalled(); }); - test('the ordinary Steer row stays gated on canSteer', async () => { - await openMenu({ pausedOnApproval: false, canSteer: false }); + test('the ordinary Steer row stays gated on canSteer', () => { + openMenu({ pausedOnApproval: false, canSteer: false }); const row = screen.getByText('com_ui_steer').closest('button'); expect(row).toHaveAttribute('aria-disabled', 'true'); @@ -107,8 +106,8 @@ describe('DuringRunSendButton — Interrupt & steer availability', () => { expect(mockSteerFromComposer).not.toHaveBeenCalled(); }); - test('both actions are available during a normal run', async () => { - await openMenu({ pausedOnApproval: false, canSteer: true }); + test('both actions are available during a normal run', () => { + openMenu({ pausedOnApproval: false, canSteer: true }); expect(screen.getByText('com_ui_interrupt_steer').closest('button')).toHaveAttribute( 'aria-disabled',