Fix tests to wrap all calls changing the UI with act. (#12268)

This commit is contained in:
Jacob Richman
2025-10-30 11:50:26 -07:00
committed by GitHub
parent cc081337b7
commit 54fa26ef0e
69 changed files with 2002 additions and 1291 deletions

View File

@@ -5,7 +5,7 @@
*/
import React from 'react';
import { render } from 'ink-testing-library';
import { render } from '../../test-utils/render.js';
import { Text } from 'ink';
import { LoadingIndicator } from './LoadingIndicator.js';
import { StreamingContext } from '../contexts/StreamingContext.js';
@@ -96,11 +96,12 @@ describe('<LoadingIndicator />', () => {
currentLoadingPhrase: 'Processing data...',
elapsedTime: 3,
};
const { lastFrame } = renderWithContext(
const { lastFrame, unmount } = renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.Responding,
);
expect(lastFrame()).toContain('Processing data...');
unmount();
});
it('should display the elapsedTime correctly when Responding', () => {
@@ -108,11 +109,12 @@ describe('<LoadingIndicator />', () => {
currentLoadingPhrase: 'Working...',
elapsedTime: 60,
};
const { lastFrame } = renderWithContext(
const { lastFrame, unmount } = renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.Responding,
);
expect(lastFrame()).toContain('(esc to cancel, 1m)');
unmount();
});
it('should display the elapsedTime correctly in human-readable format', () => {
@@ -120,24 +122,26 @@ describe('<LoadingIndicator />', () => {
currentLoadingPhrase: 'Working...',
elapsedTime: 125,
};
const { lastFrame } = renderWithContext(
const { lastFrame, unmount } = renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.Responding,
);
expect(lastFrame()).toContain('(esc to cancel, 2m 5s)');
unmount();
});
it('should render rightContent when provided', () => {
const rightContent = <Text>Extra Info</Text>;
const { lastFrame } = renderWithContext(
const { lastFrame, unmount } = renderWithContext(
<LoadingIndicator {...defaultProps} rightContent={rightContent} />,
StreamingState.Responding,
);
expect(lastFrame()).toContain('Extra Info');
unmount();
});
it('should transition correctly between states using rerender', () => {
const { lastFrame, rerender } = renderWithContext(
const { lastFrame, rerender, unmount } = renderWithContext(
<LoadingIndicator {...defaultProps} />,
StreamingState.Idle,
);
@@ -179,6 +183,7 @@ describe('<LoadingIndicator />', () => {
</StreamingContext.Provider>,
);
expect(lastFrame()).toBe('');
unmount();
});
it('should display fallback phrase if thought is empty', () => {
@@ -187,12 +192,13 @@ describe('<LoadingIndicator />', () => {
currentLoadingPhrase: 'Loading...',
elapsedTime: 5,
};
const { lastFrame } = renderWithContext(
const { lastFrame, unmount } = renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.Responding,
);
const output = lastFrame();
expect(output).toContain('Loading...');
unmount();
});
it('should display the subject of a thought', () => {
@@ -203,7 +209,7 @@ describe('<LoadingIndicator />', () => {
},
elapsedTime: 5,
};
const { lastFrame } = renderWithContext(
const { lastFrame, unmount } = renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.Responding,
);
@@ -213,6 +219,7 @@ describe('<LoadingIndicator />', () => {
expect(output).toContain('Thinking about something...');
expect(output).not.toContain('and other stuff.');
}
unmount();
});
it('should prioritize thought.subject over currentLoadingPhrase', () => {
@@ -224,17 +231,18 @@ describe('<LoadingIndicator />', () => {
currentLoadingPhrase: 'This should not be displayed',
elapsedTime: 5,
};
const { lastFrame } = renderWithContext(
const { lastFrame, unmount } = renderWithContext(
<LoadingIndicator {...props} />,
StreamingState.Responding,
);
const output = lastFrame();
expect(output).toContain('This should be displayed');
expect(output).not.toContain('This should not be displayed');
unmount();
});
it('should truncate long primary text instead of wrapping', () => {
const { lastFrame } = renderWithContext(
const { lastFrame, unmount } = renderWithContext(
<LoadingIndicator
{...defaultProps}
currentLoadingPhrase={
@@ -246,11 +254,12 @@ describe('<LoadingIndicator />', () => {
);
expect(lastFrame()).toMatchSnapshot();
unmount();
});
describe('responsive layout', () => {
it('should render on a single line on a wide terminal', () => {
const { lastFrame } = renderWithContext(
const { lastFrame, unmount } = renderWithContext(
<LoadingIndicator
{...defaultProps}
rightContent={<Text>Right</Text>}
@@ -264,10 +273,11 @@ describe('<LoadingIndicator />', () => {
expect(output).toContain('Loading...');
expect(output).toContain('(esc to cancel, 5s)');
expect(output).toContain('Right');
unmount();
});
it('should render on multiple lines on a narrow terminal', () => {
const { lastFrame } = renderWithContext(
const { lastFrame, unmount } = renderWithContext(
<LoadingIndicator
{...defaultProps}
rightContent={<Text>Right</Text>}
@@ -288,24 +298,27 @@ describe('<LoadingIndicator />', () => {
expect(lines[1]).toContain('(esc to cancel, 5s)');
expect(lines[2]).toContain('Right');
}
unmount();
});
it('should use wide layout at 80 columns', () => {
const { lastFrame } = renderWithContext(
const { lastFrame, unmount } = renderWithContext(
<LoadingIndicator {...defaultProps} />,
StreamingState.Responding,
80,
);
expect(lastFrame()?.includes('\n')).toBe(false);
unmount();
});
it('should use narrow layout at 79 columns', () => {
const { lastFrame } = renderWithContext(
const { lastFrame, unmount } = renderWithContext(
<LoadingIndicator {...defaultProps} />,
StreamingState.Responding,
79,
);
expect(lastFrame()?.includes('\n')).toBe(true);
unmount();
});
});
});