refactor(cli): integrate real config loading into async test utils (#23040)

This commit is contained in:
Tommaso Sciortino
2026-03-19 17:05:33 +00:00
committed by GitHub
parent 7de0616229
commit 23264ced9a
103 changed files with 1806 additions and 1541 deletions
@@ -75,7 +75,9 @@ describe('BaseSelectionList', () => {
...props,
};
const result = renderWithProviders(<BaseSelectionList {...defaultProps} />);
const result = await renderWithProviders(
<BaseSelectionList {...defaultProps} />,
);
await result.waitUntilReady();
return result;
};
@@ -310,7 +312,7 @@ describe('BaseSelectionList', () => {
);
const { rerender, lastFrame, waitUntilReady, unmount } =
renderWithProviders(<BaseSelectionList {...componentProps} />);
await renderWithProviders(<BaseSelectionList {...componentProps} />);
await waitUntilReady();
// Function to simulate the activeIndex changing over time
@@ -108,7 +108,7 @@ describe('BaseSettingsDialog', () => {
...props,
};
const result = renderWithProviders(
const result = await renderWithProviders(
<BaseSettingsDialog {...defaultProps} />,
);
await result.waitUntilReady();
@@ -75,7 +75,7 @@ describe('DescriptiveRadioButtonSelect', () => {
onSelect: mockOnSelect,
...props,
};
const result = renderWithProviders(
const result = await renderWithProviders(
<DescriptiveRadioButtonSelect {...defaultProps} />,
);
await result.waitUntilReady();
@@ -25,7 +25,7 @@ const NUMERIC_OPTIONS: readonly SettingEnumOption[] = [
describe('<EnumSelector />', () => {
it('renders with string options and matches snapshot', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={LANGUAGE_OPTIONS}
currentValue="en"
@@ -39,7 +39,7 @@ describe('<EnumSelector />', () => {
});
it('renders with numeric options and matches snapshot', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={NUMERIC_OPTIONS}
currentValue={2}
@@ -53,7 +53,7 @@ describe('<EnumSelector />', () => {
});
it('renders inactive state and matches snapshot', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={LANGUAGE_OPTIONS}
currentValue="zh"
@@ -70,7 +70,7 @@ describe('<EnumSelector />', () => {
const singleOption: readonly SettingEnumOption[] = [
{ label: 'Only Option', value: 'only' },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={singleOption}
currentValue="only"
@@ -84,7 +84,7 @@ describe('<EnumSelector />', () => {
});
it('renders nothing when no options are provided', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={[]}
currentValue=""
@@ -98,7 +98,7 @@ describe('<EnumSelector />', () => {
});
it('handles currentValue not found in options', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={LANGUAGE_OPTIONS}
currentValue="invalid"
@@ -114,7 +114,7 @@ describe('<EnumSelector />', () => {
it('updates when currentValue changes externally', async () => {
const { rerender, lastFrame, waitUntilReady, unmount } =
renderWithProviders(
await renderWithProviders(
<EnumSelector
options={LANGUAGE_OPTIONS}
currentValue="en"
@@ -141,7 +141,7 @@ describe('<EnumSelector />', () => {
});
it('shows navigation arrows when multiple options available', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={LANGUAGE_OPTIONS}
currentValue="en"
@@ -159,7 +159,7 @@ describe('<EnumSelector />', () => {
const singleOption: readonly SettingEnumOption[] = [
{ label: 'Only Option', value: 'only' },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<EnumSelector
options={singleOption}
currentValue="only"
@@ -28,7 +28,7 @@ describe('<HalfLinePaddedBox />', () => {
it('renders standard background and blocks when not iTerm2', async () => {
vi.mocked(isITerm2).mockReturnValue(false);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HalfLinePaddedBox backgroundBaseColor="blue" backgroundOpacity={0.5}>
<Text>Content</Text>
</HalfLinePaddedBox>,
@@ -44,7 +44,7 @@ describe('<HalfLinePaddedBox />', () => {
it('renders iTerm2-specific blocks when iTerm2 is detected', async () => {
vi.mocked(isITerm2).mockReturnValue(true);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HalfLinePaddedBox backgroundBaseColor="blue" backgroundOpacity={0.5}>
<Text>Content</Text>
</HalfLinePaddedBox>,
@@ -58,7 +58,7 @@ describe('<HalfLinePaddedBox />', () => {
});
it('renders nothing when useBackgroundColor is false', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HalfLinePaddedBox
backgroundBaseColor="blue"
backgroundOpacity={0.5}
@@ -78,7 +78,7 @@ describe('<HalfLinePaddedBox />', () => {
it('renders nothing when screen reader is enabled', async () => {
mockUseIsScreenReaderEnabled.mockReturnValue(true);
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<HalfLinePaddedBox backgroundBaseColor="blue" backgroundOpacity={0.5}>
<Text>Content</Text>
</HalfLinePaddedBox>,
@@ -288,7 +288,7 @@ describe('<MaxSizedBox />', () => {
{ length: 20 },
(_, i) => `- Step ${i + 1}: Do something important`,
).join('\n');
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<MaxSizedBox maxWidth={80} maxHeight={5} overflowDirection="bottom">
<MarkdownDisplay
text={`## Plan\n\n${markdownContent}`}
@@ -70,7 +70,7 @@ describe('RadioButtonSelect', () => {
{ label: 'Option 3', value: 'three', disabled: true, key: 'three' },
];
const renderComponent = (
const renderComponent = async (
props: Partial<RadioButtonSelectProps<string>> = {},
) => {
const defaultProps: RadioButtonSelectProps<string> = {
@@ -86,7 +86,7 @@ describe('RadioButtonSelect', () => {
});
describe('Prop forwarding to BaseSelectionList', () => {
it('should forward all props correctly when provided', () => {
it('should forward all props correctly when provided', async () => {
const props = {
items: ITEMS,
initialIndex: 1,
@@ -98,7 +98,7 @@ describe('RadioButtonSelect', () => {
showNumbers: false,
};
renderComponent(props);
await renderComponent(props);
expect(BaseSelectionList).toHaveBeenCalledTimes(1);
expect(BaseSelectionList).toHaveBeenCalledWith(
@@ -110,8 +110,8 @@ describe('RadioButtonSelect', () => {
);
});
it('should use default props if not provided', () => {
renderComponent({
it('should use default props if not provided', async () => {
await renderComponent({
items: ITEMS,
onSelect: mockOnSelect,
});
@@ -137,8 +137,8 @@ describe('RadioButtonSelect', () => {
numberColor: 'MOCK_NUMBER_COLOR',
};
beforeEach(() => {
renderComponent();
beforeEach(async () => {
await renderComponent();
renderItem = extractRenderItem();
});
@@ -29,7 +29,7 @@ describe('<Scrollable />', () => {
});
it('renders children', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Scrollable hasFocus={false} height={5}>
<Text>Hello World</Text>
</Scrollable>,
@@ -40,7 +40,7 @@ describe('<Scrollable />', () => {
});
it('renders multiple children', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Scrollable hasFocus={false} height={5}>
<Text>Line 1</Text>
<Text>Line 2</Text>
@@ -55,7 +55,7 @@ describe('<Scrollable />', () => {
});
it('matches snapshot', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<Scrollable hasFocus={false} height={5}>
<Text>Line 1</Text>
<Text>Line 2</Text>
@@ -77,7 +77,7 @@ describe('<Scrollable />', () => {
},
);
const { waitUntilReady, unmount } = renderWithProviders(
const { waitUntilReady, unmount } = await renderWithProviders(
<Scrollable hasFocus={true} height={5}>
<Text>Line 1</Text>
<Text>Line 2</Text>
@@ -105,7 +105,7 @@ describe('<Scrollable />', () => {
// Initial state with scrollToBottom={true}
unmount();
const { waitUntilReady: waitUntilReady2, unmount: unmount2 } =
renderWithProviders(
await renderWithProviders(
<Scrollable hasFocus={true} height={5} scrollToBottom={true}>
<Text>Line 1</Text>
<Text>Line 2</Text>
@@ -197,7 +197,7 @@ describe('<Scrollable />', () => {
},
);
const { stdin, waitUntilReady, unmount } = renderWithProviders(
const { stdin, waitUntilReady, unmount } = await renderWithProviders(
<Scrollable hasFocus={true} height={5}>
<Box height={scrollHeight}>
<Text>Content</Text>
@@ -132,10 +132,10 @@ describe('ScrollableList Demo Behavior', () => {
let lastFrame: (options?: { allowEmpty?: boolean }) => string | undefined;
let waitUntilReady: () => Promise<void>;
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(
result = await renderWithProviders(
<TestComponent
onAddItem={(add) => {
addItem = add;
@@ -245,9 +245,9 @@ describe('ScrollableList Demo Behavior', () => {
let lastFrame: () => string | undefined;
let waitUntilReady: () => Promise<void>;
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(<StickyTestComponent />);
result = await renderWithProviders(<StickyTestComponent />);
lastFrame = result.lastFrame;
waitUntilReady = result.waitUntilReady;
});
@@ -313,9 +313,9 @@ describe('ScrollableList Demo Behavior', () => {
title: `Item ${i}`,
}));
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(
result = await renderWithProviders(
<Box flexDirection="column" width={80} height={10}>
<ScrollableList
ref={(ref) => {
@@ -417,9 +417,9 @@ describe('ScrollableList Demo Behavior', () => {
let lastFrame: (options?: { allowEmpty?: boolean }) => string | undefined;
let waitUntilReady: () => Promise<void>;
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(
result = await renderWithProviders(
<Box width={100} height={20}>
<ScrollableList
data={items}
@@ -480,9 +480,9 @@ describe('ScrollableList Demo Behavior', () => {
);
};
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(<TestComp />);
result = await renderWithProviders(<TestComp />);
});
await result!.waitUntilReady();
@@ -601,9 +601,9 @@ describe('ScrollableList Demo Behavior', () => {
);
};
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(<TestComp />);
result = await renderWithProviders(<TestComp />);
});
await result!.waitUntilReady();
@@ -671,9 +671,9 @@ describe('ScrollableList Demo Behavior', () => {
);
};
let result: ReturnType<typeof renderWithProviders>;
let result: Awaited<ReturnType<typeof renderWithProviders>>;
await act(async () => {
result = renderWithProviders(<TestComp />);
result = await renderWithProviders(<TestComp />);
});
await result!.waitUntilReady();
@@ -79,7 +79,7 @@ describe('SearchableList', () => {
mockOnClose = vi.fn();
});
const renderList = (
const renderList = async (
props: Partial<SearchableListProps<GenericListItem>> = {},
) => {
const defaultProps: SearchableListProps<GenericListItem> = {
@@ -95,7 +95,7 @@ describe('SearchableList', () => {
};
it('should render all items initially', async () => {
const { lastFrame, waitUntilReady } = renderList();
const { lastFrame, waitUntilReady } = await renderList();
await waitUntilReady();
const frame = lastFrame();
@@ -109,7 +109,7 @@ describe('SearchableList', () => {
});
it('should reset selection to top when items change if resetSelectionOnItemsChange is true', async () => {
const { lastFrame, stdin, waitUntilReady } = renderList({
const { lastFrame, stdin, waitUntilReady } = await renderList({
resetSelectionOnItemsChange: true,
});
await waitUntilReady();
@@ -150,7 +150,7 @@ describe('SearchableList', () => {
});
it('should filter items based on search query', async () => {
const { lastFrame, stdin } = renderList();
const { lastFrame, stdin } = await renderList();
await React.act(async () => {
stdin.write('Two');
@@ -165,7 +165,7 @@ describe('SearchableList', () => {
});
it('should show "No items found." when no items match', async () => {
const { lastFrame, stdin } = renderList();
const { lastFrame, stdin } = await renderList();
await React.act(async () => {
stdin.write('xyz123');
@@ -178,7 +178,7 @@ describe('SearchableList', () => {
});
it('should handle selection with Enter', async () => {
const { stdin } = renderList();
const { stdin } = await renderList();
await React.act(async () => {
stdin.write('\r'); // Enter
@@ -190,7 +190,7 @@ describe('SearchableList', () => {
});
it('should handle navigation and selection', async () => {
const { stdin } = renderList();
const { stdin } = await renderList();
await React.act(async () => {
stdin.write('\u001B[B'); // Down arrow
@@ -206,7 +206,7 @@ describe('SearchableList', () => {
});
it('should handle close with Esc', async () => {
const { stdin } = renderList();
const { stdin } = await renderList();
await React.act(async () => {
stdin.write('\u001B'); // Esc
@@ -218,7 +218,7 @@ describe('SearchableList', () => {
});
it('should match snapshot', async () => {
const { lastFrame, waitUntilReady } = renderList();
const { lastFrame, waitUntilReady } = await renderList();
await waitUntilReady();
expect(lastFrame()).toMatchSnapshot();
});
@@ -37,7 +37,7 @@ describe('<SectionHeader />', () => {
width: 40,
},
])('$description', async ({ title, subtitle, width }) => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<SectionHeader title={title} subtitle={subtitle} />,
{ width },
);
@@ -17,7 +17,7 @@ const MOCK_TABS: Tab[] = [
describe('TabHeader', () => {
describe('rendering', () => {
it('renders null for single tab', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader
tabs={[{ key: '0', header: 'Only Tab' }]}
currentIndex={0}
@@ -29,7 +29,7 @@ describe('TabHeader', () => {
});
it('renders all tab headers', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={MOCK_TABS} currentIndex={0} />,
);
await waitUntilReady();
@@ -42,7 +42,7 @@ describe('TabHeader', () => {
});
it('renders separators between tabs', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={MOCK_TABS} currentIndex={0} />,
);
await waitUntilReady();
@@ -57,7 +57,7 @@ describe('TabHeader', () => {
describe('arrows', () => {
it('shows arrows by default', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={MOCK_TABS} currentIndex={0} />,
);
await waitUntilReady();
@@ -69,7 +69,7 @@ describe('TabHeader', () => {
});
it('hides arrows when showArrows is false', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={MOCK_TABS} currentIndex={0} showArrows={false} />,
);
await waitUntilReady();
@@ -83,7 +83,7 @@ describe('TabHeader', () => {
describe('status icons', () => {
it('shows status icons by default', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={MOCK_TABS} currentIndex={0} />,
);
await waitUntilReady();
@@ -95,7 +95,7 @@ describe('TabHeader', () => {
});
it('hides status icons when showStatusIcons is false', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={MOCK_TABS} currentIndex={0} showStatusIcons={false} />,
);
await waitUntilReady();
@@ -107,7 +107,7 @@ describe('TabHeader', () => {
});
it('shows checkmark for completed tabs', async () => {
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader
tabs={MOCK_TABS}
currentIndex={0}
@@ -130,7 +130,7 @@ describe('TabHeader', () => {
{ key: '0', header: 'Tab 1' },
{ key: '1', header: 'Review', isSpecial: true },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={tabsWithSpecial} currentIndex={0} />,
);
await waitUntilReady();
@@ -146,7 +146,7 @@ describe('TabHeader', () => {
{ key: '0', header: 'Tab 1', statusIcon: '★' },
{ key: '1', header: 'Tab 2' },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={tabsWithCustomIcon} currentIndex={0} />,
);
await waitUntilReady();
@@ -158,7 +158,7 @@ describe('TabHeader', () => {
it('uses custom renderStatusIcon when provided', async () => {
const renderStatusIcon = () => '•';
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader
tabs={MOCK_TABS}
currentIndex={0}
@@ -178,7 +178,7 @@ describe('TabHeader', () => {
{ key: '0', header: 'ThisIsAVeryLongHeaderThatShouldBeTruncated' },
{ key: '1', header: 'AnotherVeryLongHeader' },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader tabs={longTabs} currentIndex={0} />,
);
await waitUntilReady();
@@ -197,7 +197,7 @@ describe('TabHeader', () => {
it('falls back to default when renderStatusIcon returns undefined', async () => {
const renderStatusIcon = () => undefined;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
const { lastFrame, waitUntilReady, unmount } = await renderWithProviders(
<TabHeader
tabs={MOCK_TABS}
currentIndex={0}
@@ -3241,9 +3241,9 @@ describe('Transformation Utilities', () => {
},
])(
'should invalidate cache when line content changes $desc',
({ actFn, expected }) => {
async ({ actFn, expected }) => {
const viewport = { width: 80, height: 24 };
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useTextBuffer({
initialText: 'original line',
viewport,
@@ -3262,9 +3262,9 @@ describe('Transformation Utilities', () => {
},
);
it('should invalidate cache when viewport width changes', () => {
it('should invalidate cache when viewport width changes', async () => {
const viewport = { width: 80, height: 24 };
const { result, rerender } = renderHookWithProviders(
const { result, rerender } = await renderHookWithProviders(
({ vp }) =>
useTextBuffer({
initialText:
@@ -3284,10 +3284,10 @@ describe('Transformation Utilities', () => {
expect(result.current.allVisualLines.length).toBeGreaterThan(1);
});
it('should correctly handle cursor expansion/collapse in cached layout', () => {
it('should correctly handle cursor expansion/collapse in cached layout', async () => {
const viewport = { width: 80, height: 24 };
const text = 'Check @image.png here';
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useTextBuffer({
initialText: text,
viewport,
@@ -3317,10 +3317,10 @@ describe('Transformation Utilities', () => {
expect(result.current.allVisualLines[0]).toContain('[Image image.png]');
});
it('should reuse cache for unchanged lines during editing', () => {
it('should reuse cache for unchanged lines during editing', async () => {
const viewport = { width: 80, height: 24 };
const initialText = 'line 1\nline 2\nline 3';
const { result } = renderHookWithProviders(() =>
const { result } = await renderHookWithProviders(() =>
useTextBuffer({
initialText,
viewport,