Skip to content

Commit 897a89a

Browse files
committed
test: add missing tests
1 parent d62c91e commit 897a89a

File tree

4 files changed

+46
-10
lines changed

4 files changed

+46
-10
lines changed

packages/core/__tests__/utils/index.spec.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { platform } from 'node:os';
12
import { stdin, stdout } from 'node:process';
23
import * as readline from 'node:readline';
34
import { cursor } from 'sisteransi';
@@ -30,6 +31,10 @@ jest.mock('node:process', () => ({
3031
},
3132
}));
3233

34+
jest.mock('node:os', () => ({
35+
platform: jest.fn(() => 'linux'),
36+
}));
37+
3338
describe('Utils', () => {
3439
describe('isCancel()', () => {
3540
it('should verify if is cancel symbol', () => {
@@ -136,7 +141,18 @@ describe('Utils', () => {
136141

137142
block()();
138143

139-
expect(stdin.setRawMode).toHaveBeenCalledWith(false);
144+
expect(stdin.setRawMode).toHaveBeenCalledTimes(2);
145+
expect(stdin.setRawMode).toHaveBeenNthCalledWith(2, false);
146+
});
147+
148+
it('should not disable input raw mode on Windows', () => {
149+
stdin.isTTY = true;
150+
(platform as jest.Mock).mockReturnValueOnce('win32');
151+
152+
block()();
153+
154+
expect(stdin.setRawMode).toHaveBeenCalledTimes(1);
155+
expect(stdin.setRawMode).toHaveBeenCalledWith(true);
140156
});
141157

142158
it('should close readline interface', () => {

packages/core/src/utils/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1+
import { platform } from 'node:os';
12
import { stdin, stdout } from 'node:process';
23
import type { Key } from 'node:readline';
34
import * as readline from 'node:readline';
45
import { Readable } from 'node:stream';
56
import { cursor } from 'sisteransi';
67
import { hasAliasKey } from './aliases';
78

8-
const isWindows = globalThis.process.platform.startsWith('win');
9-
109
export * from './aliases';
1110
export * from './mock';
1211
export * from './string';
@@ -23,6 +22,10 @@ export function setRawMode(input: Readable, value: boolean) {
2322
if (i.isTTY) i.setRawMode(value);
2423
}
2524

25+
function isWindows(): boolean {
26+
return platform().startsWith('win');
27+
}
28+
2629
export function block({
2730
input = stdin,
2831
output = stdout,
@@ -61,7 +64,7 @@ export function block({
6164
if (hideCursor) output.write(cursor.show);
6265

6366
// Prevent Windows specific issues: https://github.com/natemoo-re/clack/issues/176
64-
if (input.isTTY && !isWindows) input.setRawMode(false);
67+
if (input.isTTY && !isWindows()) input.setRawMode(false);
6568

6669
// @ts-expect-error fix for https://github.com/nodejs/node/issues/31762#issuecomment-1441223907
6770
rl.terminal = false;

packages/prompts/__tests__/utils/format.spec.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ import { formatPlaceholder, limitOptions } from '../../src/utils';
44

55
describe('format', () => {
66
describe('limitOptions()', () => {
7+
const options = Array.from(Array(40).keys()).map(String);
78
const limit = color.dim('...');
89

910
it('should not limit options', () => {
10-
const options = Array.from(Array(10).keys()).map(String);
11-
1211
const result = limitOptions({
1312
options,
1413
maxItems: undefined,
@@ -22,7 +21,6 @@ describe('format', () => {
2221
});
2322

2423
it('should limit bottom options', () => {
25-
const options = Array.from(Array(10).keys()).map(String);
2624
const maxItems = 5;
2725

2826
const result = limitOptions({
@@ -40,7 +38,6 @@ describe('format', () => {
4038
});
4139

4240
it('should limit top options', () => {
43-
const options = Array.from(Array(10).keys()).map(String);
4441
const maxItems = 5;
4542

4643
const result = limitOptions({
@@ -58,7 +55,6 @@ describe('format', () => {
5855
});
5956

6057
it('should limit top and bottom options', () => {
61-
const options = Array.from(Array(10).keys()).map(String);
6258
const maxItems = 5;
6359
const middleOption = Math.floor(maxItems / 2);
6460
const cursor = Math.floor(options.length / 2);
@@ -77,6 +73,24 @@ describe('format', () => {
7773
expect(result[middleOption]).toBe(options[cursor]);
7874
expect(result[result.length - 1]).toBe(limit);
7975
});
76+
77+
it('should limit by terminal rows', () => {
78+
const maxTerminalRows = 20;
79+
process.stdout.rows = maxTerminalRows;
80+
81+
const result = limitOptions({
82+
options,
83+
maxItems: undefined,
84+
cursor: 0,
85+
style(option, active) {
86+
return option;
87+
},
88+
});
89+
90+
expect(result).toHaveLength(maxTerminalRows - 4);
91+
expect(result[0]).toBe(options[0]);
92+
expect(result[result.length - 1]).toBe(limit);
93+
});
8094
});
8195

8296
describe('formatPlaceholder()', () => {

packages/prompts/src/utils/format.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ export interface LimitOptionsParams<TOption> {
1010
export const limitOptions = <TOption>(params: LimitOptionsParams<TOption>): string[] => {
1111
const { cursor, options, style } = params;
1212

13+
const paramMaxItems = params.maxItems ?? Infinity;
14+
// During test `process.stdout.rows` is `undefined`, and it brakes `limitOptions` function.
15+
const outputMaxItems = Math.max((process.stdout.rows ?? Infinity) - 4, 0);
1316
// We clamp to minimum 5 because anything less doesn't make sense UX wise
14-
const maxItems = params.maxItems === undefined ? Infinity : Math.max(params.maxItems, 5);
17+
const maxItems = Math.min(outputMaxItems, Math.max(paramMaxItems, 5));
1518
let slidingWindowLocation = 0;
1619

1720
if (cursor >= slidingWindowLocation + maxItems - 3) {

0 commit comments

Comments
 (0)