summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/hooks
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src/ui/hooks')
-rw-r--r--packages/cli/src/ui/hooks/useCompletion.integration.test.ts35
-rw-r--r--packages/cli/src/ui/hooks/useCompletion.test.ts38
-rw-r--r--packages/cli/src/ui/hooks/useCompletion.ts2
3 files changed, 63 insertions, 12 deletions
diff --git a/packages/cli/src/ui/hooks/useCompletion.integration.test.ts b/packages/cli/src/ui/hooks/useCompletion.integration.test.ts
index 705b2735..37075e3c 100644
--- a/packages/cli/src/ui/hooks/useCompletion.integration.test.ts
+++ b/packages/cli/src/ui/hooks/useCompletion.integration.test.ts
@@ -55,6 +55,12 @@ describe('useCompletion git-aware filtering integration', () => {
action: vi.fn(),
},
{
+ name: 'stats',
+ altName: 'usage',
+ description: 'check session stats. Usage: /stats [model|tools]',
+ action: vi.fn(),
+ },
+ {
name: 'clear',
description: 'Clear the screen',
action: vi.fn(),
@@ -511,10 +517,27 @@ describe('useCompletion git-aware filtering integration', () => {
expect(result.current.showSuggestions).toBe(true);
});
- it('should suggest commands based on altName', async () => {
+ it.each([['/?'], ['/usage']])(
+ 'should not suggest commands when altName is fully typed',
+ async (altName) => {
+ const { result } = renderHook(() =>
+ useCompletion(
+ altName,
+ '/test/cwd',
+ true,
+ mockSlashCommands,
+ mockCommandContext,
+ ),
+ );
+
+ expect(result.current.suggestions).toHaveLength(0);
+ },
+ );
+
+ it('should suggest commands based on partial altName matches', async () => {
const { result } = renderHook(() =>
useCompletion(
- '/?',
+ '/usag', // part of the word "usage"
'/test/cwd',
true,
mockSlashCommands,
@@ -523,7 +546,11 @@ describe('useCompletion git-aware filtering integration', () => {
);
expect(result.current.suggestions).toEqual([
- { label: 'help', value: 'help', description: 'Show help' },
+ {
+ label: 'stats',
+ value: 'stats',
+ description: 'check session stats. Usage: /stats [model|tools]',
+ },
]);
});
@@ -734,7 +761,7 @@ describe('useCompletion git-aware filtering integration', () => {
expect(result.current.suggestions.length).toBe(mockSlashCommands.length);
expect(result.current.suggestions.map((s) => s.label)).toEqual(
- expect.arrayContaining(['help', 'clear', 'memory', 'chat']),
+ expect.arrayContaining(['help', 'clear', 'memory', 'chat', 'stats']),
);
});
diff --git a/packages/cli/src/ui/hooks/useCompletion.test.ts b/packages/cli/src/ui/hooks/useCompletion.test.ts
index b2790808..7f2823c7 100644
--- a/packages/cli/src/ui/hooks/useCompletion.test.ts
+++ b/packages/cli/src/ui/hooks/useCompletion.test.ts
@@ -65,6 +65,12 @@ describe('useCompletion', () => {
action: vi.fn(),
},
{
+ name: 'stats',
+ altName: 'usage',
+ description: 'check session stats. Usage: /stats [model|tools]',
+ action: vi.fn(),
+ },
+ {
name: 'clear',
description: 'Clear the screen',
action: vi.fn(),
@@ -299,7 +305,7 @@ describe('useCompletion', () => {
),
);
- expect(result.current.suggestions.length).toBe(4);
+ expect(result.current.suggestions.length).toBe(5);
expect(result.current.activeSuggestionIndex).toBe(0);
act(() => {
@@ -325,7 +331,7 @@ describe('useCompletion', () => {
act(() => {
result.current.navigateUp();
});
- expect(result.current.activeSuggestionIndex).toBe(3);
+ expect(result.current.activeSuggestionIndex).toBe(4);
});
it('should handle navigation with large suggestion lists and scrolling', () => {
@@ -372,9 +378,9 @@ describe('useCompletion', () => {
),
);
- expect(result.current.suggestions).toHaveLength(4);
+ expect(result.current.suggestions).toHaveLength(5);
expect(result.current.suggestions.map((s) => s.label)).toEqual(
- expect.arrayContaining(['help', 'clear', 'memory', 'chat']),
+ expect.arrayContaining(['help', 'clear', 'memory', 'chat', 'stats']),
);
expect(result.current.showSuggestions).toBe(true);
expect(result.current.activeSuggestionIndex).toBe(0);
@@ -397,10 +403,28 @@ describe('useCompletion', () => {
expect(result.current.suggestions[0].description).toBe('Show help');
});
- it('should suggest commands by altName', () => {
+ it.each([['/?'], ['/usage']])(
+ 'should not suggest commands when altName is fully typed',
+ (altName) => {
+ const { result } = renderHook(() =>
+ useCompletion(
+ altName,
+ testCwd,
+ true,
+ mockSlashCommands,
+ mockCommandContext,
+ mockConfig,
+ ),
+ );
+
+ expect(result.current.suggestions).toHaveLength(0);
+ },
+ );
+
+ it('should suggest commands based on partial altName matches', () => {
const { result } = renderHook(() =>
useCompletion(
- '/?',
+ '/usag', // part of the word "usage"
testCwd,
true,
mockSlashCommands,
@@ -410,7 +434,7 @@ describe('useCompletion', () => {
);
expect(result.current.suggestions).toHaveLength(1);
- expect(result.current.suggestions[0].label).toBe('help');
+ expect(result.current.suggestions[0].label).toBe('stats');
});
it('should not show suggestions for exact leaf command match', () => {
diff --git a/packages/cli/src/ui/hooks/useCompletion.ts b/packages/cli/src/ui/hooks/useCompletion.ts
index 8b3f6991..d3de5c6b 100644
--- a/packages/cli/src/ui/hooks/useCompletion.ts
+++ b/packages/cli/src/ui/hooks/useCompletion.ts
@@ -221,7 +221,7 @@ export function useCompletion(
// enter should submit immediately.
if (potentialSuggestions.length > 0 && !hasTrailingSpace) {
const perfectMatch = potentialSuggestions.find(
- (s) => s.name === partial,
+ (s) => s.name === partial || s.altName === partial,
);
if (perfectMatch && !perfectMatch.subCommands) {
potentialSuggestions = [];