Skip to content

Commit f6c4732

Browse files
committed
test: add tests for SelectList, MultiSelectList, WizardSelect, LogLink, exit-message
1 parent 6a06c25 commit f6c4732

File tree

5 files changed

+261
-0
lines changed

5 files changed

+261
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { clearExitMessage, getExitMessage, setExitMessage } from '../exit-message.js';
2+
import { afterEach, describe, expect, it } from 'vitest';
3+
4+
describe('exit-message', () => {
5+
afterEach(() => clearExitMessage());
6+
7+
it('returns null when no message set', () => {
8+
expect(getExitMessage()).toBeNull();
9+
});
10+
11+
it('stores and retrieves a message', () => {
12+
setExitMessage('Goodbye!');
13+
14+
expect(getExitMessage()).toBe('Goodbye!');
15+
});
16+
17+
it('clears the message', () => {
18+
setExitMessage('Bye');
19+
clearExitMessage();
20+
21+
expect(getExitMessage()).toBeNull();
22+
});
23+
24+
it('overwrites previous message', () => {
25+
setExitMessage('First');
26+
setExitMessage('Second');
27+
28+
expect(getExitMessage()).toBe('Second');
29+
});
30+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { LogLink } from '../LogLink.js';
2+
import { render } from 'ink-testing-library';
3+
import React from 'react';
4+
import { describe, expect, it } from 'vitest';
5+
6+
describe('LogLink', () => {
7+
it('renders with prefix and relative path', () => {
8+
const { lastFrame } = render(<LogLink filePath="/Users/dev/project/logs/deploy.log" />);
9+
10+
expect(lastFrame()).toContain('Log:');
11+
});
12+
13+
it('renders custom display text', () => {
14+
const { lastFrame } = render(<LogLink filePath="/tmp/test.log" displayText="test.log" />);
15+
16+
expect(lastFrame()).toContain('test.log');
17+
});
18+
19+
it('hides prefix when showPrefix is false', () => {
20+
const { lastFrame } = render(<LogLink filePath="/tmp/test.log" showPrefix={false} />);
21+
22+
expect(lastFrame()).not.toContain('Log:');
23+
});
24+
25+
it('renders custom label', () => {
26+
const { lastFrame } = render(<LogLink filePath="/tmp/test.log" label="Output" />);
27+
28+
expect(lastFrame()).toContain('Output:');
29+
});
30+
});
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { MultiSelectList } from '../MultiSelectList.js';
2+
import { render } from 'ink-testing-library';
3+
import React from 'react';
4+
import { describe, expect, it } from 'vitest';
5+
6+
describe('MultiSelectList', () => {
7+
const items = [
8+
{ id: 'agent-1', title: 'Agent One' },
9+
{ id: 'agent-2', title: 'Agent Two', description: 'Secondary agent' },
10+
{ id: 'agent-3', title: 'Agent Three' },
11+
];
12+
13+
it('renders all items with checkboxes', () => {
14+
const { lastFrame } = render(<MultiSelectList items={items} selectedIndex={0} selectedIds={new Set()} />);
15+
16+
expect(lastFrame()).toContain('Agent One');
17+
expect(lastFrame()).toContain('Agent Two');
18+
expect(lastFrame()).toContain('Agent Three');
19+
expect(lastFrame()).toContain('[ ]');
20+
});
21+
22+
it('shows checked items', () => {
23+
const { lastFrame } = render(
24+
<MultiSelectList items={items} selectedIndex={0} selectedIds={new Set(['agent-1', 'agent-3'])} />
25+
);
26+
27+
expect(lastFrame()).toContain('[✓]');
28+
});
29+
30+
it('shows cursor on current index', () => {
31+
const { lastFrame } = render(<MultiSelectList items={items} selectedIndex={1} selectedIds={new Set()} />);
32+
33+
expect(lastFrame()).toContain('❯');
34+
});
35+
36+
it('shows descriptions', () => {
37+
const { lastFrame } = render(<MultiSelectList items={items} selectedIndex={0} selectedIds={new Set()} />);
38+
39+
expect(lastFrame()).toContain('Secondary agent');
40+
});
41+
42+
it('shows empty state when no items', () => {
43+
const { lastFrame } = render(<MultiSelectList items={[]} selectedIndex={0} selectedIds={new Set()} />);
44+
45+
expect(lastFrame()).toContain('No agents found');
46+
});
47+
48+
it('shows custom empty message', () => {
49+
const { lastFrame } = render(
50+
<MultiSelectList items={[]} selectedIndex={0} selectedIds={new Set()} emptyMessage="No targets" />
51+
);
52+
53+
expect(lastFrame()).toContain('No targets');
54+
});
55+
});
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { SelectList } from '../SelectList.js';
2+
import { render } from 'ink-testing-library';
3+
import React from 'react';
4+
import { describe, expect, it } from 'vitest';
5+
6+
describe('SelectList', () => {
7+
const items = [
8+
{ id: 'a', title: 'Agent', description: 'Add an agent' },
9+
{ id: 'b', title: 'Memory', description: 'Add memory' },
10+
{ id: 'c', title: 'Identity' },
11+
];
12+
13+
it('renders all items', () => {
14+
const { lastFrame } = render(<SelectList items={items} selectedIndex={0} />);
15+
16+
expect(lastFrame()).toContain('Agent');
17+
expect(lastFrame()).toContain('Memory');
18+
expect(lastFrame()).toContain('Identity');
19+
});
20+
21+
it('shows cursor on selected item', () => {
22+
const { lastFrame } = render(<SelectList items={items} selectedIndex={1} />);
23+
24+
expect(lastFrame()).toContain('❯');
25+
expect(lastFrame()).toContain('Memory');
26+
});
27+
28+
it('shows descriptions when provided', () => {
29+
const { lastFrame } = render(<SelectList items={items} selectedIndex={0} />);
30+
31+
expect(lastFrame()).toContain('Add an agent');
32+
expect(lastFrame()).toContain('Add memory');
33+
});
34+
35+
it('shows empty state when no items', () => {
36+
const { lastFrame } = render(<SelectList items={[]} selectedIndex={0} />);
37+
38+
expect(lastFrame()).toContain('No matches');
39+
expect(lastFrame()).toContain('No items available');
40+
});
41+
42+
it('shows custom empty message', () => {
43+
const { lastFrame } = render(<SelectList items={[]} selectedIndex={0} emptyMessage="Nothing here" />);
44+
45+
expect(lastFrame()).toContain('Nothing here');
46+
});
47+
48+
it('renders disabled items', () => {
49+
const disabledItems = [
50+
{ id: 'a', title: 'Available' },
51+
{ id: 'b', title: 'Disabled', disabled: true },
52+
];
53+
54+
const { lastFrame } = render(<SelectList items={disabledItems} selectedIndex={0} />);
55+
56+
expect(lastFrame()).toContain('Available');
57+
expect(lastFrame()).toContain('Disabled');
58+
});
59+
});
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { WizardMultiSelect, WizardSelect } from '../WizardSelect.js';
2+
import { render } from 'ink-testing-library';
3+
import React from 'react';
4+
import { describe, expect, it } from 'vitest';
5+
6+
describe('WizardSelect', () => {
7+
const items = [
8+
{ id: 'strands', title: 'Strands', description: 'AWS Strands SDK' },
9+
{ id: 'langchain', title: 'LangChain' },
10+
];
11+
12+
it('renders title and items', () => {
13+
const { lastFrame } = render(<WizardSelect title="Select SDK" items={items} selectedIndex={0} />);
14+
15+
expect(lastFrame()).toContain('Select SDK');
16+
expect(lastFrame()).toContain('Strands');
17+
expect(lastFrame()).toContain('LangChain');
18+
});
19+
20+
it('renders description when provided', () => {
21+
const { lastFrame } = render(
22+
<WizardSelect title="Pick one" description="Choose your framework" items={items} selectedIndex={0} />
23+
);
24+
25+
expect(lastFrame()).toContain('Choose your framework');
26+
});
27+
28+
it('does not render description when not provided', () => {
29+
const { lastFrame } = render(<WizardSelect title="Pick one" items={items} selectedIndex={0} />);
30+
31+
expect(lastFrame()).toContain('Pick one');
32+
expect(lastFrame()).toContain('Strands');
33+
});
34+
35+
it('passes empty message to SelectList', () => {
36+
const { lastFrame } = render(<WizardSelect title="Pick one" items={[]} selectedIndex={0} emptyMessage="No SDKs" />);
37+
38+
expect(lastFrame()).toContain('No SDKs');
39+
});
40+
});
41+
42+
describe('WizardMultiSelect', () => {
43+
const items = [
44+
{ id: 'agent-1', title: 'Agent A' },
45+
{ id: 'agent-2', title: 'Agent B' },
46+
];
47+
48+
it('renders title and items', () => {
49+
const { lastFrame } = render(
50+
<WizardMultiSelect title="Select agents" items={items} cursorIndex={0} selectedIds={new Set()} />
51+
);
52+
53+
expect(lastFrame()).toContain('Select agents');
54+
expect(lastFrame()).toContain('Agent A');
55+
expect(lastFrame()).toContain('Agent B');
56+
});
57+
58+
it('renders description when provided', () => {
59+
const { lastFrame } = render(
60+
<WizardMultiSelect
61+
title="Agents"
62+
description="Select which agents"
63+
items={items}
64+
cursorIndex={0}
65+
selectedIds={new Set()}
66+
/>
67+
);
68+
69+
expect(lastFrame()).toContain('Select which agents');
70+
});
71+
72+
it('shows checked items', () => {
73+
const { lastFrame } = render(
74+
<WizardMultiSelect title="Agents" items={items} cursorIndex={0} selectedIds={new Set(['agent-1'])} />
75+
);
76+
77+
expect(lastFrame()).toContain('[✓]');
78+
});
79+
80+
it('passes empty message', () => {
81+
const { lastFrame } = render(
82+
<WizardMultiSelect title="Agents" items={[]} cursorIndex={0} selectedIds={new Set()} emptyMessage="No agents" />
83+
);
84+
85+
expect(lastFrame()).toContain('No agents');
86+
});
87+
});

0 commit comments

Comments
 (0)