Skip to content

Commit 7995cbd

Browse files
committed
Refactor watch mode prompts.
1 parent 1f900d0 commit 7995cbd

File tree

3 files changed

+168
-159
lines changed

3 files changed

+168
-159
lines changed

packages/jest-cli/src/TestNamePatternPrompt.js

+79-81
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
'use strict';
1212

13-
import type {Config} from 'types/Config';
13+
import type {TestResult} from 'types/TestResult';
1414

1515
const ansiEscapes = require('ansi-escapes');
1616
const chalk = require('chalk');
@@ -30,108 +30,106 @@ const usage = () =>
3030

3131
const usageRows = usage().split('\n').length;
3232

33-
module.exports = (
34-
config: Config,
35-
pipe: stream$Writable | tty$WriteStream,
36-
prompt: Prompt,
37-
) => {
38-
class TestNamePatternPrompt {
39-
// $FlowFixMe
40-
_cachedTestResults;
41-
42-
constructor() {
43-
(this: any).onChange = this.onChange.bind(this);
44-
}
33+
module.exports = class TestNamePatternPrompt {
34+
_cachedTestResults: Array<TestResult>;
35+
_pipe: stream$Writable | tty$WriteStream;
36+
_prompt: Prompt;
4537

46-
run(onSuccess: Function, onCancel: Function) {
47-
pipe.write(ansiEscapes.cursorHide);
48-
pipe.write(ansiEscapes.clearScreen);
49-
pipe.write(usage());
50-
pipe.write(ansiEscapes.cursorShow);
38+
constructor(pipe: stream$Writable | tty$WriteStream, prompt: Prompt) {
39+
this._pipe = pipe;
40+
this._prompt = prompt;
41+
(this: any).onChange = this.onChange.bind(this);
42+
}
5143

52-
prompt.enter(this.onChange, onSuccess, onCancel);
53-
}
44+
run(onSuccess: Function, onCancel: Function) {
45+
this._pipe.write(ansiEscapes.cursorHide);
46+
this._pipe.write(ansiEscapes.clearScreen);
47+
this._pipe.write(usage());
48+
this._pipe.write(ansiEscapes.cursorShow);
5449

55-
onChange(pattern: string) {
56-
pipe.write(ansiEscapes.eraseLine);
57-
pipe.write(ansiEscapes.cursorLeft);
58-
this.printTypeahead(pattern, 10);
59-
}
50+
this._prompt.enter(this.onChange, onSuccess, onCancel);
51+
}
6052

61-
printTypeahead(pattern: string, max: number) {
62-
const matchedTests = this.getMatchedTests(pattern);
53+
onChange(pattern: string) {
54+
this._pipe.write(ansiEscapes.eraseLine);
55+
this._pipe.write(ansiEscapes.cursorLeft);
56+
this.printTypeahead(pattern, 10);
57+
}
6358

64-
const total = matchedTests.length;
65-
const results = matchedTests.slice(0, max);
66-
const inputText = `${chalk.dim(' pattern \u203A')} ${pattern}`;
59+
printTypeahead(pattern: string, max: number) {
60+
const matchedTests = this.getMatchedTests(pattern);
6761

68-
pipe.write(ansiEscapes.eraseDown);
69-
pipe.write(inputText);
70-
pipe.write(ansiEscapes.cursorSavePosition);
62+
const total = matchedTests.length;
63+
const results = matchedTests.slice(0, max);
64+
const inputText = `${chalk.dim(' pattern \u203A')} ${pattern}`;
7165

72-
if (pattern) {
73-
if (total) {
74-
pipe.write(`\n\n Pattern matches ${total} ${pluralizeTest(total)}`);
75-
} else {
76-
pipe.write(`\n\n Pattern matches no tests`);
77-
}
66+
this._pipe.write(ansiEscapes.eraseDown);
67+
this._pipe.write(inputText);
68+
this._pipe.write(ansiEscapes.cursorSavePosition);
7869

79-
pipe.write(' from cached test suites.');
70+
if (pattern) {
71+
if (total) {
72+
this._pipe.write(
73+
`\n\n Pattern matches ${total} ${pluralizeTest(total)}`,
74+
);
75+
} else {
76+
this._pipe.write(`\n\n Pattern matches no tests`);
77+
}
8078

81-
const width = getTerminalWidth();
79+
this._pipe.write(' from cached test suites.');
8280

83-
results.forEach(name => {
84-
const testName = formatTestNameByPattern(name, pattern, width - 4);
81+
const width = getTerminalWidth();
8582

86-
pipe.write(`\n ${chalk.dim('\u203A')} ${testName}`);
87-
});
83+
results.forEach(name => {
84+
const testName = formatTestNameByPattern(name, pattern, width - 4);
8885

89-
if (total > max) {
90-
const more = total - max;
91-
pipe.write(
92-
// eslint-disable-next-line max-len
93-
`\n ${chalk.dim(`\u203A and ${more} more ${pluralizeTest(more)}`)}`,
94-
);
95-
}
96-
} else {
97-
pipe.write(
86+
this._pipe.write(`\n ${chalk.dim('\u203A')} ${testName}`);
87+
});
88+
89+
if (total > max) {
90+
const more = total - max;
91+
this._pipe.write(
9892
// eslint-disable-next-line max-len
99-
`\n\n ${chalk.italic.yellow('Start typing to filter by a test name regex pattern.')}`,
93+
`\n ${chalk.dim(`\u203A and ${more} more ${pluralizeTest(more)}`)}`,
10094
);
10195
}
102-
103-
pipe.write(ansiEscapes.cursorTo(stringLength(inputText), usageRows - 1));
104-
pipe.write(ansiEscapes.cursorRestorePosition);
96+
} else {
97+
this._pipe.write(
98+
// eslint-disable-next-line max-len
99+
`\n\n ${chalk.italic.yellow('Start typing to filter by a test name regex pattern.')}`,
100+
);
105101
}
106102

107-
getMatchedTests(pattern: string) {
108-
let regex;
103+
this._pipe.write(
104+
ansiEscapes.cursorTo(stringLength(inputText), usageRows - 1),
105+
);
106+
this._pipe.write(ansiEscapes.cursorRestorePosition);
107+
}
109108

110-
try {
111-
regex = new RegExp(pattern, 'i');
112-
} catch (e) {
113-
return [];
114-
}
109+
getMatchedTests(pattern: string) {
110+
let regex;
115111

116-
const matchedTests = [];
112+
try {
113+
regex = new RegExp(pattern, 'i');
114+
} catch (e) {
115+
return [];
116+
}
117117

118-
this._cachedTestResults.forEach(({testResults}) =>
119-
testResults.forEach(({
120-
title,
121-
}) => {
122-
if (regex.test(title)) {
123-
matchedTests.push(title);
124-
}
125-
}));
118+
const matchedTests = [];
126119

127-
return matchedTests;
128-
}
120+
this._cachedTestResults.forEach(({testResults}) =>
121+
testResults.forEach(({
122+
title,
123+
}) => {
124+
if (regex.test(title)) {
125+
matchedTests.push(title);
126+
}
127+
}));
129128

130-
// $FlowFixMe
131-
updateCachedTestResults(testResults) {
132-
this._cachedTestResults = testResults || [];
133-
}
129+
return matchedTests;
134130
}
135131

136-
return new TestNamePatternPrompt();
132+
updateCachedTestResults(testResults: Array<TestResult>) {
133+
this._cachedTestResults = testResults || [];
134+
}
137135
};

packages/jest-cli/src/TestPathPatternPrompt.js

+85-74
Original file line numberDiff line numberDiff line change
@@ -33,93 +33,104 @@ const usage = () =>
3333

3434
const usageRows = usage().split('\n').length;
3535

36-
module.exports = (
37-
config: Config,
38-
pipe: stream$Writable | tty$WriteStream,
39-
prompt: Prompt,
40-
) => {
41-
class TestPathPatternPrompt {
42-
searchSource: SearchSource;
43-
44-
constructor() {
45-
(this: any).onChange = this.onChange.bind(this);
46-
}
36+
module.exports = class TestPathPatternPrompt {
37+
_config: Config;
38+
_pipe: stream$Writable | tty$WriteStream;
39+
_prompt: Prompt;
40+
_searchSource: SearchSource;
41+
42+
constructor(
43+
config: Config,
44+
pipe: stream$Writable | tty$WriteStream,
45+
prompt: Prompt,
46+
) {
47+
this._config = config;
48+
this._pipe = pipe;
49+
this._prompt = prompt;
50+
(this: any).onChange = this.onChange.bind(this);
51+
}
4752

48-
run(onSuccess: Function, onCancel: Function) {
49-
pipe.write(ansiEscapes.cursorHide);
50-
pipe.write(ansiEscapes.clearScreen);
51-
pipe.write(usage());
52-
pipe.write(ansiEscapes.cursorShow);
53+
run(onSuccess: Function, onCancel: Function) {
54+
this._pipe.write(ansiEscapes.cursorHide);
55+
this._pipe.write(ansiEscapes.clearScreen);
56+
this._pipe.write(usage());
57+
this._pipe.write(ansiEscapes.cursorShow);
5358

54-
prompt.enter(this.onChange, onSuccess, onCancel);
55-
}
59+
this._prompt.enter(this.onChange, onSuccess, onCancel);
60+
}
5661

57-
onChange(pattern: string) {
58-
let regex;
62+
onChange(pattern: string) {
63+
let regex;
5964

60-
try {
61-
regex = new RegExp(pattern, 'i');
62-
} catch (e) {}
65+
try {
66+
regex = new RegExp(pattern, 'i');
67+
} catch (e) {}
6368

64-
const paths = regex
65-
? this.searchSource.findMatchingTests(pattern).paths
66-
: [];
69+
const paths = regex
70+
? this._searchSource.findMatchingTests(pattern).paths
71+
: [];
6772

68-
pipe.write(ansiEscapes.eraseLine);
69-
pipe.write(ansiEscapes.cursorLeft);
70-
this.printTypeahead(pattern, paths, 10);
71-
}
73+
this._pipe.write(ansiEscapes.eraseLine);
74+
this._pipe.write(ansiEscapes.cursorLeft);
75+
this.printTypeahead(pattern, paths, 10);
76+
}
7277

73-
printTypeahead(pattern: string, allResults: Array<Path>, max: number) {
74-
const total = allResults.length;
75-
const results = allResults.slice(0, max);
76-
const inputText = `${chalk.dim(' pattern \u203A')} ${pattern}`;
77-
78-
pipe.write(ansiEscapes.eraseDown);
79-
pipe.write(inputText);
80-
pipe.write(ansiEscapes.cursorSavePosition);
81-
82-
if (pattern) {
83-
if (total) {
84-
pipe.write(`\n\n Pattern matches ${total} ${pluralizeFile(total)}.`);
85-
} else {
86-
pipe.write(`\n\n Pattern matches no files.`);
87-
}
88-
89-
const width = getTerminalWidth();
90-
const prefix = ` ${chalk.dim('\u203A')} `;
91-
const padding = stringLength(prefix) + 2;
92-
93-
results
94-
.map(rawPath => {
95-
const filePath = trimAndFormatPath(padding, config, rawPath, width);
96-
return highlight(rawPath, filePath, pattern, config.rootDir);
97-
})
98-
.forEach(filePath =>
99-
pipe.write(`\n ${chalk.dim('\u203A')} ${filePath}`));
100-
101-
if (total > max) {
102-
const more = total - max;
103-
pipe.write(
104-
// eslint-disable-next-line max-len
105-
`\n ${chalk.dim(`\u203A and ${more} more ${pluralizeFile(more)}`)}`,
106-
);
107-
}
78+
printTypeahead(pattern: string, allResults: Array<Path>, max: number) {
79+
const total = allResults.length;
80+
const results = allResults.slice(0, max);
81+
const inputText = `${chalk.dim(' pattern \u203A')} ${pattern}`;
82+
83+
this._pipe.write(ansiEscapes.eraseDown);
84+
this._pipe.write(inputText);
85+
this._pipe.write(ansiEscapes.cursorSavePosition);
86+
87+
if (pattern) {
88+
if (total) {
89+
this._pipe.write(
90+
`\n\n Pattern matches ${total} ${pluralizeFile(total)}.`,
91+
);
10892
} else {
109-
pipe.write(
93+
this._pipe.write(`\n\n Pattern matches no files.`);
94+
}
95+
96+
const width = getTerminalWidth();
97+
const prefix = ` ${chalk.dim('\u203A')} `;
98+
const padding = stringLength(prefix) + 2;
99+
100+
results
101+
.map(rawPath => {
102+
const filePath = trimAndFormatPath(
103+
padding,
104+
this._config,
105+
rawPath,
106+
width,
107+
);
108+
return highlight(rawPath, filePath, pattern, this._config.rootDir);
109+
})
110+
.forEach(filePath =>
111+
this._pipe.write(`\n ${chalk.dim('\u203A')} ${filePath}`));
112+
113+
if (total > max) {
114+
const more = total - max;
115+
this._pipe.write(
110116
// eslint-disable-next-line max-len
111-
`\n\n ${chalk.italic.yellow('Start typing to filter by a filename regex pattern.')}`,
117+
`\n ${chalk.dim(`\u203A and ${more} more ${pluralizeFile(more)}`)}`,
112118
);
113119
}
114-
115-
pipe.write(ansiEscapes.cursorTo(stringLength(inputText), usageRows - 1));
116-
pipe.write(ansiEscapes.cursorRestorePosition);
120+
} else {
121+
this._pipe.write(
122+
// eslint-disable-next-line max-len
123+
`\n\n ${chalk.italic.yellow('Start typing to filter by a filename regex pattern.')}`,
124+
);
117125
}
118126

119-
updateSearchSource(context: Context) {
120-
this.searchSource = new SearchSource(context, config);
121-
}
127+
this._pipe.write(
128+
ansiEscapes.cursorTo(stringLength(inputText), usageRows - 1),
129+
);
130+
this._pipe.write(ansiEscapes.cursorRestorePosition);
122131
}
123132

124-
return new TestPathPatternPrompt();
133+
updateSearchSource(context: Context) {
134+
this._searchSource = new SearchSource(context, this._config);
135+
}
125136
};

0 commit comments

Comments
 (0)