@abacus-ai/cli 2.0.0-canary.1 → 2.0.0-canary.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/dist/index.mjs +450 -422
  2. package/package.json +4 -1
  3. package/.oxlintrc.json +0 -8
  4. package/resources/abacus.ico +0 -0
  5. package/resources/entitlements.plist +0 -9
  6. package/src/__e2e__/README.md +0 -196
  7. package/src/__e2e__/agent-interactions.e2e.test.tsx +0 -61
  8. package/src/__e2e__/cli-commands.e2e.test.tsx +0 -77
  9. package/src/__e2e__/conversation-throttle.e2e.test.ts +0 -453
  10. package/src/__e2e__/conversation.e2e.test.tsx +0 -56
  11. package/src/__e2e__/diff-preview.e2e.test.tsx +0 -3399
  12. package/src/__e2e__/file-creation.e2e.test.tsx +0 -149
  13. package/src/__e2e__/helpers/test-helpers.ts +0 -449
  14. package/src/__e2e__/keyboard-navigation.e2e.test.tsx +0 -34
  15. package/src/__e2e__/llm-models.e2e.test.ts +0 -402
  16. package/src/__e2e__/mcp/mcp-callback-flow.e2e.test.tsx +0 -71
  17. package/src/__e2e__/mcp/mcp-full-app-ui.e2e.test.tsx +0 -167
  18. package/src/__e2e__/mcp/mcp-ui-rendering.e2e.test.tsx +0 -185
  19. package/src/__e2e__/repl.e2e.test.tsx +0 -78
  20. package/src/__e2e__/shell-compatibility.e2e.test.tsx +0 -76
  21. package/src/__e2e__/theme-mcp.e2e.test.tsx +0 -98
  22. package/src/__e2e__/tool-permissions.e2e.test.tsx +0 -66
  23. package/src/args.ts +0 -22
  24. package/src/components/__tests__/react-compiler.test.tsx +0 -78
  25. package/src/components/__tests__/status-indicator.test.tsx +0 -403
  26. package/src/components/composer/__tests__/bash-runner.test.tsx +0 -263
  27. package/src/components/composer/agent-mode-indicator.tsx +0 -63
  28. package/src/components/composer/bash-runner.tsx +0 -54
  29. package/src/components/composer/commands/default-commands.tsx +0 -615
  30. package/src/components/composer/commands/handler.tsx +0 -59
  31. package/src/components/composer/commands/picker.tsx +0 -273
  32. package/src/components/composer/commands/registry.ts +0 -233
  33. package/src/components/composer/commands/types.ts +0 -33
  34. package/src/components/composer/context.tsx +0 -88
  35. package/src/components/composer/file-mention-picker.tsx +0 -83
  36. package/src/components/composer/help.tsx +0 -44
  37. package/src/components/composer/index.tsx +0 -1007
  38. package/src/components/composer/mentions.ts +0 -57
  39. package/src/components/composer/message-queue.tsx +0 -70
  40. package/src/components/composer/mode-panel.tsx +0 -35
  41. package/src/components/composer/modes/__tests__/bash-handler.test.tsx +0 -755
  42. package/src/components/composer/modes/__tests__/bash-renderer.test.tsx +0 -1108
  43. package/src/components/composer/modes/bash-handler.tsx +0 -132
  44. package/src/components/composer/modes/bash-renderer.tsx +0 -175
  45. package/src/components/composer/modes/default-handlers.tsx +0 -33
  46. package/src/components/composer/modes/index.ts +0 -41
  47. package/src/components/composer/modes/types.ts +0 -21
  48. package/src/components/composer/persistent-shell.ts +0 -283
  49. package/src/components/composer/process.ts +0 -65
  50. package/src/components/composer/types.ts +0 -9
  51. package/src/components/composer/use-mention-search.ts +0 -68
  52. package/src/components/error-boundry.tsx +0 -60
  53. package/src/components/exit-message.tsx +0 -29
  54. package/src/components/expanded-view.tsx +0 -74
  55. package/src/components/file-completion.tsx +0 -127
  56. package/src/components/header.tsx +0 -47
  57. package/src/components/logo.tsx +0 -37
  58. package/src/components/segments.tsx +0 -356
  59. package/src/components/status-indicator.tsx +0 -306
  60. package/src/components/tool-group-summary.tsx +0 -263
  61. package/src/components/tool-permissions/ask-user-question-permission-ui.tsx +0 -319
  62. package/src/components/tool-permissions/diff-preview.tsx +0 -359
  63. package/src/components/tool-permissions/index.ts +0 -5
  64. package/src/components/tool-permissions/permission-options.tsx +0 -401
  65. package/src/components/tool-permissions/permission-preview-header.tsx +0 -57
  66. package/src/components/tool-permissions/tool-permission-ui.tsx +0 -420
  67. package/src/components/tools/agent/ask-user-question.tsx +0 -107
  68. package/src/components/tools/agent/enter-plan-mode.tsx +0 -55
  69. package/src/components/tools/agent/exit-plan-mode.tsx +0 -83
  70. package/src/components/tools/agent/handoff-to-main.tsx +0 -27
  71. package/src/components/tools/agent/subagent.tsx +0 -37
  72. package/src/components/tools/agent/todo-write.tsx +0 -104
  73. package/src/components/tools/browser/close-tab.tsx +0 -58
  74. package/src/components/tools/browser/computer.tsx +0 -70
  75. package/src/components/tools/browser/get-interactive-elements.tsx +0 -54
  76. package/src/components/tools/browser/get-tab-content.tsx +0 -51
  77. package/src/components/tools/browser/navigate-to.tsx +0 -59
  78. package/src/components/tools/browser/new-tab.tsx +0 -60
  79. package/src/components/tools/browser/perform-action.tsx +0 -63
  80. package/src/components/tools/browser/refresh-tab.tsx +0 -43
  81. package/src/components/tools/browser/switch-tab.tsx +0 -58
  82. package/src/components/tools/filesystem/delete-file.tsx +0 -104
  83. package/src/components/tools/filesystem/edit.tsx +0 -220
  84. package/src/components/tools/filesystem/list-dir.tsx +0 -78
  85. package/src/components/tools/filesystem/read-file.tsx +0 -180
  86. package/src/components/tools/filesystem/upload-image.tsx +0 -76
  87. package/src/components/tools/ide/ide-diagnostics.tsx +0 -62
  88. package/src/components/tools/index.ts +0 -91
  89. package/src/components/tools/mcp/mcp-tool.tsx +0 -158
  90. package/src/components/tools/search/fetch-url.tsx +0 -73
  91. package/src/components/tools/search/file-search.tsx +0 -78
  92. package/src/components/tools/search/grep.tsx +0 -90
  93. package/src/components/tools/search/semantic-search.tsx +0 -66
  94. package/src/components/tools/search/web-search.tsx +0 -71
  95. package/src/components/tools/shared/index.tsx +0 -48
  96. package/src/components/tools/shared/zod-coercion.ts +0 -35
  97. package/src/components/tools/terminal/bash-tool-output.tsx +0 -188
  98. package/src/components/tools/terminal/get-terminal-output.tsx +0 -91
  99. package/src/components/tools/terminal/run-in-terminal.tsx +0 -131
  100. package/src/components/tools/types.ts +0 -16
  101. package/src/components/tools.tsx +0 -68
  102. package/src/components/ui/__tests__/divider.test.tsx +0 -61
  103. package/src/components/ui/__tests__/gradient.test.tsx +0 -125
  104. package/src/components/ui/__tests__/input.test.tsx +0 -166
  105. package/src/components/ui/__tests__/select.test.tsx +0 -273
  106. package/src/components/ui/__tests__/shimmer.test.tsx +0 -99
  107. package/src/components/ui/blinking-indicator.tsx +0 -27
  108. package/src/components/ui/divider.tsx +0 -162
  109. package/src/components/ui/gradient.tsx +0 -56
  110. package/src/components/ui/input.tsx +0 -228
  111. package/src/components/ui/select.tsx +0 -151
  112. package/src/components/ui/shimmer.tsx +0 -76
  113. package/src/context/agent-mode.tsx +0 -95
  114. package/src/context/extension-file.tsx +0 -136
  115. package/src/context/network-activity.tsx +0 -45
  116. package/src/context/notification.tsx +0 -62
  117. package/src/context/shell-size.tsx +0 -49
  118. package/src/context/shell-title.tsx +0 -38
  119. package/src/entrypoints/print-mode.ts +0 -312
  120. package/src/entrypoints/repl.tsx +0 -389
  121. package/src/hooks/use-agent.ts +0 -15
  122. package/src/hooks/use-api-client.ts +0 -1
  123. package/src/hooks/use-available-height.ts +0 -8
  124. package/src/hooks/use-cleanup.ts +0 -29
  125. package/src/hooks/use-interrupt-manager.ts +0 -242
  126. package/src/hooks/use-models.ts +0 -22
  127. package/src/index.ts +0 -217
  128. package/src/lib/__tests__/ansi.test.ts +0 -255
  129. package/src/lib/__tests__/cli.test.ts +0 -122
  130. package/src/lib/__tests__/commands.test.ts +0 -325
  131. package/src/lib/__tests__/constants.test.ts +0 -15
  132. package/src/lib/__tests__/focusables.test.ts +0 -25
  133. package/src/lib/__tests__/fs.test.ts +0 -231
  134. package/src/lib/__tests__/markdown.test.tsx +0 -348
  135. package/src/lib/__tests__/mcpCommandHandler.test.ts +0 -173
  136. package/src/lib/__tests__/mcpManagement.test.ts +0 -38
  137. package/src/lib/__tests__/path-paste.test.ts +0 -144
  138. package/src/lib/__tests__/path.test.ts +0 -300
  139. package/src/lib/__tests__/queries.test.ts +0 -39
  140. package/src/lib/__tests__/standaloneMcpService.test.ts +0 -71
  141. package/src/lib/__tests__/text-buffer.test.ts +0 -328
  142. package/src/lib/__tests__/text-utils.test.ts +0 -32
  143. package/src/lib/__tests__/timing.test.ts +0 -78
  144. package/src/lib/__tests__/utils.test.ts +0 -238
  145. package/src/lib/__tests__/vim-buffer-actions.test.ts +0 -154
  146. package/src/lib/ansi.ts +0 -150
  147. package/src/lib/cli-push-server.ts +0 -112
  148. package/src/lib/cli.ts +0 -44
  149. package/src/lib/clipboard.ts +0 -226
  150. package/src/lib/command-utils.ts +0 -93
  151. package/src/lib/commands.ts +0 -270
  152. package/src/lib/constants.ts +0 -3
  153. package/src/lib/extension-connection.ts +0 -181
  154. package/src/lib/focusables.ts +0 -7
  155. package/src/lib/fs.ts +0 -533
  156. package/src/lib/markdown/code-block.tsx +0 -63
  157. package/src/lib/markdown/index.ts +0 -4
  158. package/src/lib/markdown/link.tsx +0 -19
  159. package/src/lib/markdown/markdown.tsx +0 -372
  160. package/src/lib/markdown/types.ts +0 -15
  161. package/src/lib/mcpCommandHandler.ts +0 -121
  162. package/src/lib/mcpManagement.ts +0 -44
  163. package/src/lib/path-paste.ts +0 -185
  164. package/src/lib/path.ts +0 -179
  165. package/src/lib/queries.ts +0 -15
  166. package/src/lib/standaloneMcpService.ts +0 -688
  167. package/src/lib/status-utils.ts +0 -237
  168. package/src/lib/test-utils.tsx +0 -72
  169. package/src/lib/text-buffer.ts +0 -2415
  170. package/src/lib/text-utils.ts +0 -272
  171. package/src/lib/timing.ts +0 -63
  172. package/src/lib/types.ts +0 -295
  173. package/src/lib/utils.ts +0 -182
  174. package/src/lib/vim-buffer-actions.ts +0 -732
  175. package/src/providers/agent.tsx +0 -1063
  176. package/src/providers/api-client.tsx +0 -43
  177. package/src/services/logger.ts +0 -85
  178. package/src/terminal/detection.ts +0 -187
  179. package/src/terminal/exit.ts +0 -279
  180. package/src/terminal/notification.ts +0 -83
  181. package/src/terminal/progress.ts +0 -201
  182. package/src/terminal/setup.ts +0 -797
  183. package/src/terminal/types.ts +0 -51
  184. package/src/theme/context.tsx +0 -57
  185. package/src/theme/index.ts +0 -4
  186. package/src/theme/themed.tsx +0 -35
  187. package/src/theme/themes.json +0 -546
  188. package/src/theme/types.ts +0 -110
  189. package/src/tools/types.ts +0 -59
  190. package/src/tools/utils/__tests__/zod-coercion.test.ts +0 -33
  191. package/src/tools/utils/tool-ui-components.tsx +0 -649
  192. package/src/tools/utils/zod-coercion.ts +0 -35
  193. package/tsconfig.json +0 -16
  194. package/tsconfig.node.json +0 -29
  195. package/tsconfig.test.json +0 -27
  196. package/tsdown.config.ts +0 -17
  197. package/vitest.config.ts +0 -76
@@ -1,125 +0,0 @@
1
- import { Text } from "@codellm/jar";
2
- import stripAnsi from "strip-ansi";
3
- import { describe, expect } from "vitest";
4
-
5
- // TODO: re-enable when jar testing utilities are available
6
- import { render, logInk, cleanup } from "../../../lib/test-utils.js";
7
- import { Gradient } from "../gradient.js";
8
-
9
- describe.concurrent("Gradient", () => {
10
- afterEach(() => {
11
- cleanup();
12
- });
13
-
14
- it("should render text with a named gradient", () => {
15
- const instance = render(
16
- <Gradient name="rainbow">
17
- <Text>Hello World</Text>
18
- </Gradient>,
19
- );
20
-
21
- logInk(instance);
22
-
23
- const output = instance.frames.join("");
24
- const plainText = "Hello World";
25
-
26
- expect(output).toBeDefined();
27
- expect(typeof output).toBe("string");
28
- // The gradient should apply ANSI color codes to the text
29
- expect(stripAnsi(output)).toContain(plainText);
30
- // Verify that ANSI codes are present (output should be longer than plain text)
31
- expect(output.length).toBeGreaterThan(plainText.length);
32
- // Verify ANSI escape sequences are present (should contain escape character)
33
- expect(output).toMatch(new RegExp(String.fromCharCode(27) + "\\["));
34
- });
35
-
36
- it("should render text with custom colors", () => {
37
- const instance = render(
38
- <Gradient colors={["#ff0000", "#0000ff"]}>
39
- <Text>Test Text</Text>
40
- </Gradient>,
41
- );
42
-
43
- logInk(instance);
44
-
45
- const output = instance.frames.join("");
46
- const plainText = "Test Text";
47
-
48
- expect(output).toBeDefined();
49
- expect(stripAnsi(output)).toContain(plainText);
50
- // Verify that ANSI codes are present (output should be longer than plain text)
51
- expect(output.length).toBeGreaterThan(plainText.length);
52
- // Verify ANSI escape sequences are present
53
- expect(output).toMatch(new RegExp(String.fromCharCode(27) + "\\["));
54
- });
55
-
56
- const gradientNames = [
57
- "atlas",
58
- "cristal",
59
- "teen",
60
- "mind",
61
- "morning",
62
- "vice",
63
- "passion",
64
- "fruit",
65
- "instagram",
66
- "retro",
67
- "summer",
68
- "pastel",
69
- "rainbow",
70
- ] as const;
71
- for (const name of gradientNames) {
72
- it(`should handle gradient name: ${name}`, () => {
73
- const instance = render(
74
- <Gradient name={name}>
75
- <Text>Test Text</Text>
76
- </Gradient>,
77
- );
78
-
79
- logInk(instance);
80
-
81
- const output = instance.frames.join("");
82
- const plainText = "Test Text";
83
-
84
- expect(output).toBeDefined();
85
- expect(stripAnsi(output)).toContain(plainText);
86
- // Verify that ANSI codes are present
87
- expect(output.length).toBeGreaterThan(plainText.length);
88
- expect(output).toMatch(new RegExp(String.fromCharCode(27) + "\\["));
89
- });
90
- }
91
-
92
- it("should handle multiline text", () => {
93
- const instance = render(
94
- <Gradient name="rainbow">
95
- <Text>Line 1{"\n"}Line 2</Text>
96
- </Gradient>,
97
- );
98
-
99
- logInk(instance);
100
-
101
- const output = instance.frames.join("");
102
-
103
- expect(output).toBeDefined();
104
- expect(stripAnsi(output)).toContain("Line 1");
105
- expect(stripAnsi(output)).toContain("Line 2");
106
- // Verify that ANSI codes are present
107
- expect(output).toMatch(new RegExp(String.fromCharCode(27) + "\\["));
108
- });
109
-
110
- it("should handle empty text", () => {
111
- const instance = render(
112
- <Gradient name="rainbow">
113
- <Text></Text>
114
- </Gradient>,
115
- );
116
-
117
- logInk(instance);
118
-
119
- const output = instance.frames.join("");
120
-
121
- expect(output).toBeDefined();
122
- // Empty text should still be valid (may or may not have ANSI codes)
123
- expect(typeof output).toBe("string");
124
- });
125
- });
@@ -1,166 +0,0 @@
1
- import { createRef } from "react";
2
- import { describe, expect, it, vi } from "vitest";
3
-
4
- import { stripAnsi } from "../../../lib/ansi.js";
5
- import { render, logInk, cleanup } from "../../../lib/test-utils.js";
6
- import { Input } from "../input.js";
7
-
8
- describe.concurrent("Input", () => {
9
- const TestWrapper = ({ children }: React.PropsWithChildren) => <>{children}</>;
10
-
11
- afterEach(() => {
12
- cleanup();
13
- });
14
-
15
- it("should render with placeholder", () => {
16
- const instance = render(
17
- <TestWrapper>
18
- <Input placeholder="Enter text..." />
19
- </TestWrapper>,
20
- );
21
-
22
- logInk(instance);
23
-
24
- const output = stripAnsi(instance.frames.join(""));
25
-
26
- expect(output).toBeDefined();
27
- expect(typeof output).toBe("string");
28
- expect(output).toContain("Enter text...");
29
- });
30
-
31
- it("should render with initial value", () => {
32
- const instance = render(
33
- <TestWrapper>
34
- <Input initialValue="Hello" />
35
- </TestWrapper>,
36
- );
37
-
38
- logInk(instance);
39
-
40
- const output = stripAnsi(instance.frames.join(""));
41
-
42
- expect(output).toBeDefined();
43
- expect(output).toContain("Hello");
44
- });
45
-
46
- it("should call onChange when value changes", () => {
47
- const onChange = vi.fn();
48
- render(
49
- <TestWrapper>
50
- <Input onChange={onChange} />
51
- </TestWrapper>,
52
- );
53
-
54
- // Note: Testing actual keypress events would require more complex setup
55
- // This test verifies the component renders correctly with the onChange prop
56
- expect(onChange).toBeDefined();
57
- });
58
-
59
- it("should call onSubmit when enter is pressed", () => {
60
- const onSubmit = vi.fn();
61
- render(
62
- <TestWrapper>
63
- <Input initialValue="test" onSubmit={onSubmit} />
64
- </TestWrapper>,
65
- );
66
-
67
- // Note: Testing actual keypress events would require more complex setup
68
- // This test verifies the component renders correctly with the onSubmit prop
69
- expect(onSubmit).toBeDefined();
70
- });
71
-
72
- it("should handle ref", () => {
73
- const ref = createRef<any>();
74
- render(
75
- <TestWrapper>
76
- <Input ref={ref} />
77
- </TestWrapper>,
78
- );
79
-
80
- // The ref should be set after render
81
- expect(ref.current).toBeDefined();
82
- });
83
-
84
- it("should render with custom placeholder props", () => {
85
- const instance = render(
86
- <TestWrapper>
87
- <Input placeholder="Custom" placeholderProps={{ color: "blue" }} />
88
- </TestWrapper>,
89
- );
90
-
91
- logInk(instance);
92
-
93
- const output = stripAnsi(instance.frames.join(""));
94
-
95
- expect(output).toBeDefined();
96
- expect(output).toContain("Custom");
97
- });
98
-
99
- it("should handle disabled state", () => {
100
- const instance = render(
101
- <TestWrapper>
102
- <Input disabled placeholder="Disabled input" />
103
- </TestWrapper>,
104
- );
105
-
106
- logInk(instance);
107
-
108
- const output = stripAnsi(instance.frames.join(""));
109
-
110
- expect(output).toBeDefined();
111
- expect(output).toContain("Disabled input");
112
- });
113
-
114
- it("should handle grammar highlighting", () => {
115
- const grammar = [
116
- { regex: /\d+/g, color: "red" },
117
- { regex: /[a-z]+/g, color: "blue" },
118
- ];
119
-
120
- const instance = render(
121
- <TestWrapper>
122
- <Input initialValue="test123" grammar={grammar} />
123
- </TestWrapper>,
124
- );
125
-
126
- logInk(instance);
127
-
128
- const output = stripAnsi(instance.frames.join(""));
129
-
130
- expect(output).toBeDefined();
131
- expect(output).toContain("test");
132
- expect(output).toContain("123");
133
- });
134
-
135
- it("should handle onKeyDown callback", () => {
136
- const onKeyDown = vi.fn();
137
- render(
138
- <TestWrapper>
139
- <Input onKeyDown={onKeyDown} />
140
- </TestWrapper>,
141
- );
142
-
143
- // Note: Testing actual keypress events would require more complex setup
144
- // This test verifies the component renders correctly with the onKeyDown prop
145
- expect(onKeyDown).toBeDefined();
146
- });
147
-
148
- it("should handle width and height constraints", () => {
149
- const instance = render(
150
- <TestWrapper>
151
- <Input
152
- initialValue="This is a long text that should be constrained"
153
- width={20}
154
- height={5}
155
- />
156
- </TestWrapper>,
157
- );
158
-
159
- logInk(instance);
160
-
161
- const output = stripAnsi(instance.frames.join(""));
162
-
163
- expect(output).toBeDefined();
164
- expect(output).toContain("This is a long");
165
- });
166
- });
@@ -1,273 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
-
3
- import { cleanup, render, logInk } from "../../../lib/test-utils.js";
4
- import { Select } from "../select.js";
5
-
6
- describe.concurrent("Select", () => {
7
- const TestWrapper = ({ children }: React.PropsWithChildren) => <>{children}</>;
8
-
9
- afterEach(() => {
10
- cleanup();
11
- });
12
-
13
- it("should render items", () => {
14
- const items = ["Item 1", "Item 2", "Item 3"];
15
- const instance = render(
16
- <TestWrapper>
17
- <Select items={items} />
18
- </TestWrapper>,
19
- );
20
-
21
- logInk(instance);
22
-
23
- const output = instance.frames.join("");
24
-
25
- expect(output).toBeDefined();
26
- expect(typeof output).toBe("string");
27
- expect(output).toContain("Item 1");
28
- expect(output).toContain("Item 2");
29
- expect(output).toContain("Item 3");
30
- });
31
-
32
- it("should highlight the first item by default", () => {
33
- const items = ["First", "Second", "Third"];
34
- const instance = render(
35
- <TestWrapper>
36
- <Select items={items} />
37
- </TestWrapper>,
38
- );
39
-
40
- logInk(instance);
41
-
42
- const output = instance.frames.join("");
43
-
44
- expect(output).toBeDefined();
45
- // The selected item should have a '>' prefix
46
- expect(output).toContain("> First");
47
- });
48
-
49
- it("should use initialIndex to set initial selection", () => {
50
- const items = ["First", "Second", "Third"];
51
- const instance = render(
52
- <TestWrapper>
53
- <Select items={items} initialIndex={1} />
54
- </TestWrapper>,
55
- );
56
-
57
- logInk(instance);
58
-
59
- const output = instance.frames.join("");
60
-
61
- expect(output).toBeDefined();
62
- expect(output).toContain("> Second");
63
- });
64
-
65
- it('should show "No matches" when items array is empty', () => {
66
- const instance = render(
67
- <TestWrapper>
68
- <Select items={[]} />
69
- </TestWrapper>,
70
- );
71
-
72
- logInk(instance);
73
-
74
- const output = instance.frames.join("");
75
-
76
- expect(output).toBeDefined();
77
- expect(output).toContain("No matches");
78
- });
79
-
80
- it("should respect limit prop", () => {
81
- const items = Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`);
82
- const instance = render(
83
- <TestWrapper>
84
- <Select items={items} limit={5} />
85
- </TestWrapper>,
86
- );
87
-
88
- logInk(instance);
89
-
90
- const output = instance.frames.join("");
91
-
92
- expect(output).toBeDefined();
93
- // Should only show up to limit items
94
- expect(output).toContain("Item 1");
95
- expect(output).toContain("Item 5");
96
- // Should not show items beyond limit
97
- expect(output).not.toContain("Item 6");
98
- });
99
-
100
- it("should show index when showIndex is true", () => {
101
- const items = ["Item 1", "Item 2", "Item 3"];
102
- const instance = render(
103
- <TestWrapper>
104
- <Select items={items} showIndex={true} />
105
- </TestWrapper>,
106
- );
107
-
108
- logInk(instance);
109
-
110
- const output = instance.frames.join("");
111
-
112
- expect(output).toBeDefined();
113
- // Should show index like (1/3)
114
- expect(output).toContain("(1/3)");
115
- });
116
-
117
- it("should not show index when showIndex is false", () => {
118
- const items = ["Item 1", "Item 2", "Item 3"];
119
- const instance = render(
120
- <TestWrapper>
121
- <Select items={items} showIndex={false} />
122
- </TestWrapper>,
123
- );
124
-
125
- logInk(instance);
126
-
127
- const output = instance.frames.join("");
128
-
129
- expect(output).toBeDefined();
130
- // Should not show index
131
- expect(output).not.toContain("(1/3)");
132
- });
133
-
134
- it("should show indicators when showIndicators is true and there are more items", () => {
135
- const items = Array.from({ length: 15 }, (_, i) => `Item ${i + 1}`);
136
- const instance = render(
137
- <TestWrapper>
138
- <Select items={items} limit={5} showIndicators={true} />
139
- </TestWrapper>,
140
- );
141
-
142
- logInk(instance);
143
-
144
- const output = instance.frames.join("");
145
-
146
- expect(output).toBeDefined();
147
- // Should show scroll indicators when there are more items
148
- expect(output).toContain("▼");
149
- });
150
-
151
- it("should call onHighlight when selection changes", () => {
152
- const onHighlight = vi.fn();
153
- const items = ["Item 1", "Item 2", "Item 3"];
154
- render(
155
- <TestWrapper>
156
- <Select items={items} onHighlight={onHighlight} />
157
- </TestWrapper>,
158
- );
159
-
160
- // onHighlight should be called with the initial selection
161
- // Note: Testing actual keypress events would require more complex setup
162
- expect(onHighlight).toBeDefined();
163
- });
164
-
165
- it("should call onSubmit when enter is pressed", () => {
166
- const onSubmit = vi.fn();
167
- const items = ["Item 1", "Item 2", "Item 3"];
168
- render(
169
- <TestWrapper>
170
- <Select items={items} onSubmit={onSubmit} />
171
- </TestWrapper>,
172
- );
173
-
174
- // Note: Testing actual keypress events would require more complex setup
175
- // This test verifies the component renders correctly with the onSubmit prop
176
- expect(onSubmit).toBeDefined();
177
- });
178
-
179
- it("should call onCancel when escape is pressed", () => {
180
- const onCancel = vi.fn();
181
- const items = ["Item 1", "Item 2", "Item 3"];
182
- render(
183
- <TestWrapper>
184
- <Select items={items} onCancel={onCancel} />
185
- </TestWrapper>,
186
- );
187
-
188
- // Note: Testing actual keypress events would require more complex setup
189
- // This test verifies the component renders correctly with the onCancel prop
190
- expect(onCancel).toBeDefined();
191
- });
192
-
193
- it("should call onTab when tab is pressed", () => {
194
- const onTab = vi.fn();
195
- const items = ["Item 1", "Item 2", "Item 3"];
196
- render(
197
- <TestWrapper>
198
- <Select items={items} onTab={onTab} />
199
- </TestWrapper>,
200
- );
201
-
202
- // Note: Testing actual keypress events would require more complex setup
203
- // This test verifies the component renders correctly with the onTab prop
204
- expect(onTab).toBeDefined();
205
- });
206
-
207
- it("should respect isActive prop", () => {
208
- const items = ["Item 1", "Item 2", "Item 3"];
209
- const instance = render(
210
- <TestWrapper>
211
- <Select items={items} isActive={false} />
212
- </TestWrapper>,
213
- );
214
-
215
- logInk(instance);
216
-
217
- const output = instance.frames.join("");
218
-
219
- expect(output).toBeDefined();
220
- expect(output).toContain("Item 1");
221
- });
222
-
223
- it("should handle maxHeight constraint", () => {
224
- const items = Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`);
225
- const instance = render(
226
- <TestWrapper>
227
- <Select items={items} limit={10} maxHeight={5} />
228
- </TestWrapper>,
229
- );
230
-
231
- logInk(instance);
232
-
233
- const output = instance.frames.join("");
234
-
235
- expect(output).toBeDefined();
236
- // Should respect maxHeight constraint
237
- expect(output).toContain("Item 1");
238
- });
239
-
240
- it("should clamp initialIndex to valid range", () => {
241
- const items = ["Item 1", "Item 2", "Item 3"];
242
- const instance = render(
243
- <TestWrapper>
244
- <Select items={items} initialIndex={10} />
245
- </TestWrapper>,
246
- );
247
-
248
- logInk(instance);
249
-
250
- const output = instance.frames.join("");
251
-
252
- expect(output).toBeDefined();
253
- // Should clamp to last item (index 2)
254
- expect(output).toContain("> Item 3");
255
- });
256
-
257
- it("should handle negative initialIndex", () => {
258
- const items = ["Item 1", "Item 2", "Item 3"];
259
- const instance = render(
260
- <TestWrapper>
261
- <Select items={items} initialIndex={-1} />
262
- </TestWrapper>,
263
- );
264
-
265
- logInk(instance);
266
-
267
- const output = instance.frames.join("");
268
-
269
- expect(output).toBeDefined();
270
- // Should clamp to first item (index 0)
271
- expect(output).toContain("> Item 1");
272
- });
273
- });
@@ -1,99 +0,0 @@
1
- import stripAnsi from "strip-ansi";
2
- import { describe, expect } from "vitest";
3
-
4
- import { render, logInk, cleanup } from "../../../lib/test-utils.js";
5
- import { Shimmer } from "../shimmer.js";
6
-
7
- describe.concurrent("Shimmer", () => {
8
- afterEach(() => {
9
- cleanup();
10
- });
11
-
12
- it("should render text with shimmer effect", () => {
13
- const instance = render(<Shimmer text="Hello World Shimmer" />);
14
-
15
- logInk(instance);
16
-
17
- const output = instance.frames.join("");
18
- const plainText = "Hello World Shimmer";
19
-
20
- expect(output).toBeDefined();
21
- expect(typeof output).toBe("string");
22
- expect(stripAnsi(output)).toContain(plainText);
23
- // Verify that ANSI codes are present (output should be longer than plain text)
24
- expect(output.length).toBeGreaterThan(plainText.length);
25
- // Verify ANSI escape sequences are present
26
- expect(output).toMatch(new RegExp(String.fromCharCode(27) + "\\["));
27
- });
28
-
29
- it("should render with custom color", () => {
30
- const instance = render(<Shimmer text="Test" color="#ff0000" />);
31
-
32
- logInk(instance);
33
-
34
- const output = instance.frames.join("");
35
- const plainText = "Test";
36
-
37
- expect(output).toBeDefined();
38
- expect(stripAnsi(output)).toContain(plainText);
39
- // Verify that ANSI codes are present
40
- expect(output.length).toBeGreaterThan(plainText.length);
41
- expect(output).toMatch(new RegExp(String.fromCharCode(27) + "\\["));
42
- });
43
-
44
- it("should handle empty text", () => {
45
- const instance = render(<Shimmer text="" />);
46
-
47
- logInk(instance);
48
-
49
- const output = instance.frames.join("");
50
-
51
- expect(output).toBeDefined();
52
- });
53
-
54
- it("should handle single character", () => {
55
- const instance = render(<Shimmer text="A" />);
56
-
57
- logInk(instance);
58
-
59
- const output = instance.frames.join("");
60
- const plainText = "A";
61
-
62
- expect(output).toBeDefined();
63
- expect(stripAnsi(output)).toContain(plainText);
64
- // Verify that ANSI codes are present
65
- expect(output.length).toBeGreaterThan(plainText.length);
66
- expect(output).toMatch(new RegExp(String.fromCharCode(27) + "\\["));
67
- });
68
-
69
- it("should handle long text", () => {
70
- const longText =
71
- "This is a very long text that should still render properly with the shimmer effect";
72
- const instance = render(<Shimmer text={longText} />);
73
-
74
- logInk(instance);
75
-
76
- const output = instance.frames.join("");
77
-
78
- expect(output).toBeDefined();
79
- expect(stripAnsi(output)).toContain(longText);
80
- // Verify that ANSI codes are present
81
- expect(output.length).toBeGreaterThan(longText.length);
82
- expect(output).toMatch(new RegExp(String.fromCharCode(27) + "\\["));
83
- });
84
-
85
- it("should use default color when not provided", () => {
86
- const instance = render(<Shimmer text="Default Shimmer" />);
87
-
88
- logInk(instance);
89
-
90
- const output = instance.frames.join("");
91
- const plainText = "Default Shimmer";
92
-
93
- expect(output).toBeDefined();
94
- expect(stripAnsi(output)).toContain(plainText);
95
- // Verify that ANSI codes are present
96
- expect(output.length).toBeGreaterThan(plainText.length);
97
- expect(output).toMatch(new RegExp(String.fromCharCode(27) + "\\["));
98
- });
99
- });
@@ -1,27 +0,0 @@
1
- import { Text } from "@codellm/jar";
2
- import { memo, startTransition, useEffect, useState } from "react";
3
-
4
- interface BlinkingIndicatorProps {
5
- char: string;
6
- color?: string;
7
- }
8
-
9
- const BLINK_INTERVAL = 500; // ms
10
-
11
- export const BlinkingIndicator = memo(({ char, color }: BlinkingIndicatorProps) => {
12
- const [visible, setVisible] = useState(true);
13
-
14
- useEffect(() => {
15
- const interval = setInterval(() => {
16
- startTransition(() => {
17
- setVisible((prev) => !prev);
18
- });
19
- }, BLINK_INTERVAL);
20
-
21
- return () => clearInterval(interval);
22
- }, []);
23
-
24
- return <Text color={color}>{visible ? char : " "}</Text>;
25
- });
26
-
27
- BlinkingIndicator.displayName = "BlinkingIndicator";