import { waitFor } from '@testing-library/dom' import { expect, test, vi } from 'vitest' import * as cliLogin from '@/data/cli/login' import { ProfileContextType } from '@/lib/profile' import { CliLoginScreen } from '@/pages/cli/login' import { customRender } from '@/tests/lib/custom-render' const DEFAULT_PROFILE_CONTEXT: ProfileContextType = { profile: { id: 1, auth0_id: 'auth0|test', gotrue_id: 'gotrue-test', username: 'testuser', primary_email: 'test@example.com', first_name: null, last_name: null, mobile: null, is_alpha_user: false, is_sso_user: false, disabled_features: [], free_project_limit: null, }, error: null, isLoading: false, isError: false, isSuccess: true, } test('still navigates after parent re-renders during an in-flight POST', async () => { // Resolve manually so we can inject a re-render while the POST is in flight. let resolveSession: (value: { nonce: string }) => void = () => {} const createCliLoginSessionMock = vi.spyOn(cliLogin, 'createCliLoginSession').mockImplementation( () => new Promise<{ nonce: string }>((resolve) => { resolveSession = resolve }) ) const initialNavigate = vi.fn() const { rerender } = customRender( , { profileContext: DEFAULT_PROFILE_CONTEXT } ) await waitFor(() => { expect(createCliLoginSessionMock).toHaveBeenCalledTimes(1) }) // Parent re-renders mid-POST with a brand-new navigate ref. This was the // production hang: the cleanup would invalidate the success handler and // the ref guard would skip the retry, leaving the screen on the loader. const laterNavigate = vi.fn() rerender( ) resolveSession({ nonce: 'ABCDEFGH12345678' }) await waitFor(() => { expect(laterNavigate).toHaveBeenCalledWith('/cli/login?device_code=ABCDEFGH') }) expect(initialNavigate).not.toHaveBeenCalled() expect(createCliLoginSessionMock).toHaveBeenCalledTimes(1) })