diff --git a/packages/cli/src/ui/components/InputPrompt.test.tsx b/packages/cli/src/ui/components/InputPrompt.test.tsx index 7c523620..cf8b9685 100644 --- a/packages/cli/src/ui/components/InputPrompt.test.tsx +++ b/packages/cli/src/ui/components/InputPrompt.test.tsx @@ -1252,8 +1252,7 @@ describe('InputPrompt', () => { unmount(); }); - // Skip: trailing cursor (inverted space at EOL) is trimmed without right border - it.skip('should display cursor at the end of the line as an inverted space', async () => { + it('should display cursor at the end of the line as an inverted space', async () => { mockBuffer.text = 'hello'; mockBuffer.lines = ['hello']; mockBuffer.viewportVisualLines = ['hello']; @@ -1303,13 +1302,12 @@ describe('InputPrompt', () => { unmount(); }); - // Skip: trailing cursor (inverted space at EOL) is trimmed without right border - it.skip('should display cursor at the end of a line with unicode characters', async () => { + it('should display cursor at the end of a line with unicode characters', async () => { const text = 'hello 👍'; mockBuffer.text = text; mockBuffer.lines = [text]; mockBuffer.viewportVisualLines = [text]; - mockBuffer.visualCursor = [0, 8]; // cursor after '👍' (length is 6 + 2 for emoji) + mockBuffer.visualCursor = [0, 7]; // cursor after '👍' (emoji is 1 code point, so total is 7) const { stdout, unmount } = renderWithProviders( , @@ -1396,8 +1394,7 @@ describe('InputPrompt', () => { unmount(); }); - // Skip: trailing cursor (inverted space at EOL) is trimmed without right border - it.skip('should display cursor at the end of a line in a multiline block', async () => { + it('should display cursor at the end of a line in a multiline block', async () => { const text = 'first line\nsecond line'; mockBuffer.text = text; mockBuffer.lines = text.split('\n'); @@ -1469,7 +1466,7 @@ describe('InputPrompt', () => { // Check that all lines, including the empty one, are rendered. // This implicitly tests that the Box wrapper provides height for the empty line. expect(frame).toContain('hello'); - expect(frame).toContain('world'); + expect(frame).toContain(`world${chalk.inverse(' ')}`); const outputLines = frame!.split('\n'); // The number of lines should be 2 for the border plus 3 for the content. diff --git a/packages/cli/src/ui/components/InputPrompt.tsx b/packages/cli/src/ui/components/InputPrompt.tsx index 4eaf535f..7d174250 100644 --- a/packages/cli/src/ui/components/InputPrompt.tsx +++ b/packages/cli/src/ui/components/InputPrompt.tsx @@ -834,9 +834,10 @@ export const InputPrompt: React.FC = ({ isOnCursorLine && cursorVisualColAbsolute === cpLen(lineText) ) { + // Add zero-width space after cursor to prevent Ink from trimming trailing whitespace renderedLine.push( - {showCursor ? chalk.inverse(' ') : ' '} + {showCursor ? chalk.inverse(' ') + '\u200B' : ' \u200B'} , ); }