jest-watch-typeahead 2.2.0 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -15,7 +15,6 @@ export default class FileNamePlugin {
15
15
  prompt: config.prompt || 'filter by a filename regex pattern'
16
16
  };
17
17
  }
18
-
19
18
  apply(jestHooks) {
20
19
  jestHooks.onFileChange(({
21
20
  projects
@@ -23,11 +22,9 @@ export default class FileNamePlugin {
23
22
  this._projects = projects;
24
23
  });
25
24
  }
26
-
27
25
  onKey(key) {
28
26
  this._prompt.put(key);
29
27
  }
30
-
31
28
  run(globalConfig, updateConfigAndRun) {
32
29
  const p = new FileNamePatternPrompt(this._stdout, this._prompt);
33
30
  p.updateSearchSources(this._projects);
@@ -41,9 +38,7 @@ export default class FileNamePlugin {
41
38
  }, rej);
42
39
  });
43
40
  }
44
-
45
41
  getUsageInfo() {
46
42
  return this._usageInfo;
47
43
  }
48
-
49
44
  }
@@ -12,22 +12,17 @@ export default class FileNamePatternPrompt extends PatternPrompt {
12
12
  this._entityName = 'filenames';
13
13
  this._searchSources = [];
14
14
  }
15
-
16
15
  _onChange(pattern, options) {
17
16
  super._onChange(pattern, options);
18
-
19
17
  this._printTypeahead(pattern, options);
20
18
  }
21
-
22
19
  _printTypeahead(pattern, options) {
23
20
  const matchedTests = this._getMatchedTests(pattern);
24
-
25
21
  const total = matchedTests.length;
26
22
  const pipe = this._pipe;
27
23
  const prompt = this._prompt;
28
24
  printPatternCaret(pattern, pipe);
29
25
  pipe.write(ansiEscapes.cursorLeft);
30
-
31
26
  if (pattern) {
32
27
  printPatternMatches(total, 'file', pipe);
33
28
  const prefix = ` ${chalk.dim('\u203A')} `;
@@ -46,26 +41,21 @@ export default class FileNamePatternPrompt extends PatternPrompt {
46
41
  const filePath = trimAndFormatPath(padding, context.config, path, width);
47
42
  return highlight(path, filePath, pattern);
48
43
  }).map((item, i) => formatTypeaheadSelection(item, i, index, prompt)).forEach(item => printTypeaheadItem(item, pipe));
49
-
50
44
  if (total > end) {
51
45
  printMore('file', pipe, total - end);
52
46
  }
53
47
  } else {
54
48
  printStartTyping('filename', pipe);
55
49
  }
56
-
57
50
  printRestoredPatternCaret(pattern, this._currentUsageRows, pipe);
58
51
  }
59
-
60
52
  _getMatchedTests(pattern) {
61
53
  let regex;
62
-
63
54
  try {
64
55
  regex = new RegExp(pattern, 'i');
65
56
  } catch (e) {
66
57
  return [];
67
58
  }
68
-
69
59
  return this._searchSources.reduce((tests, {
70
60
  testPaths,
71
61
  config
@@ -78,15 +68,12 @@ export default class FileNamePatternPrompt extends PatternPrompt {
78
68
  })));
79
69
  }, []);
80
70
  }
81
-
82
71
  updateSearchSources(searchSources) {
83
72
  this._searchSources = searchSources;
84
73
  }
85
-
86
74
  run(onSuccess, onCancel, options) {
87
75
  super.run(value => {
88
76
  onSuccess(removeTrimmingDots(value).split('/').map(escapeStrForRegex).join('/'));
89
77
  }, onCancel, options);
90
78
  }
91
-
92
79
  }
@@ -1,8 +1,6 @@
1
1
  import chalk from 'chalk';
2
2
  import stripAnsi from 'strip-ansi';
3
-
4
3
  const pluralize = (count, text) => count === 1 ? text : `${text}s`;
5
-
6
4
  export const printPatternMatches = (count, entity, pipe, extraText = '') => {
7
5
  const pluralized = pluralize(count, entity);
8
6
  const result = count ? `\n\n Pattern matches ${count} ${pluralized}` : `\n\n Pattern matches no ${pluralized}`;
@@ -22,6 +20,5 @@ export const formatTypeaheadSelection = (item, index, activeIndex, prompt) => {
22
20
  prompt.setPromptSelection(stripAnsi(item));
23
21
  return chalk.black.bgYellow(stripAnsi(item));
24
22
  }
25
-
26
23
  return item;
27
24
  };
@@ -5,22 +5,18 @@ const scroll = (size, {
5
5
  let start = 0;
6
6
  let index = Math.min(offset, size);
7
7
  const halfScreen = max / 2;
8
-
9
8
  if (index <= halfScreen) {
10
9
  start = 0;
11
10
  } else {
12
11
  if (size >= max) {
13
12
  start = Math.min(index - halfScreen - 1, size - max);
14
13
  }
15
-
16
14
  index = Math.min(index - start, size);
17
15
  }
18
-
19
16
  return {
20
17
  end: Math.min(size, start + max),
21
18
  index,
22
19
  start
23
20
  };
24
21
  };
25
-
26
22
  export default scroll;
@@ -4,7 +4,6 @@ import slash from 'slash';
4
4
  import stripAnsi from 'strip-ansi';
5
5
  const TRIMMING_DOTS = '...';
6
6
  const ENTER = '⏎';
7
-
8
7
  const relativePath = (config, testPath) => {
9
8
  const relativeTestPath = path.relative(config.cwd || config.rootDir, testPath);
10
9
  const dirname = path.dirname(relativeTestPath);
@@ -14,9 +13,7 @@ const relativePath = (config, testPath) => {
14
13
  dirname
15
14
  };
16
15
  };
17
-
18
16
  const colorize = (str, start, end) => chalk.dim(str.slice(0, start)) + chalk.reset(str.slice(start, end)) + chalk.dim(str.slice(end));
19
-
20
17
  export const trimAndFormatPath = (pad, config, testPath, columns) => {
21
18
  const maxLength = columns - pad;
22
19
  const relative = relativePath(config, testPath);
@@ -25,50 +22,43 @@ export const trimAndFormatPath = (pad, config, testPath, columns) => {
25
22
  } = relative;
26
23
  let {
27
24
  dirname
28
- } = relative; // length is ok
25
+ } = relative;
29
26
 
27
+ // length is ok
30
28
  if ((dirname + path.sep + basename).length <= maxLength) {
31
29
  return slash(chalk.dim(dirname + path.sep) + chalk.bold(basename));
32
- } // we can fit trimmed dirname and full basename
33
-
30
+ }
34
31
 
32
+ // we can fit trimmed dirname and full basename
35
33
  const basenameLength = basename.length;
36
-
37
34
  if (basenameLength + 4 < maxLength) {
38
35
  const dirnameLength = maxLength - 4 - basenameLength;
39
36
  dirname = `${TRIMMING_DOTS}${dirname.slice(dirname.length - dirnameLength, dirname.length)}`;
40
37
  return slash(chalk.dim(dirname + path.sep) + chalk.bold(basename));
41
38
  }
42
-
43
39
  if (basenameLength + 4 === maxLength) {
44
40
  return slash(chalk.dim(`${TRIMMING_DOTS}${path.sep}`) + chalk.bold(basename));
45
- } // can't fit dirname, but can fit trimmed basename
46
-
47
-
41
+ }
42
+ // can't fit dirname, but can fit trimmed basename
48
43
  return slash(chalk.bold(`${TRIMMING_DOTS}${basename.slice(-maxLength + 3)}`));
49
44
  };
50
45
  export const getTerminalWidth = (pipe = process.stdout) => pipe.columns;
51
46
  export const highlight = (rawPath, filePath, pattern) => {
52
47
  const relativePathHead = './';
53
48
  let regexp;
54
-
55
49
  try {
56
50
  regexp = new RegExp(pattern, 'i');
57
51
  } catch (e) {
58
52
  return chalk.dim(filePath);
59
53
  }
60
-
61
54
  const strippedRawPath = stripAnsi(rawPath);
62
55
  const strippedFilePath = stripAnsi(filePath);
63
56
  const match = strippedRawPath.match(regexp);
64
-
65
57
  if (!match || match.index == null) {
66
58
  return chalk.dim(strippedFilePath);
67
59
  }
68
-
69
60
  const offset = strippedRawPath.length - strippedFilePath.length;
70
61
  let trimLength;
71
-
72
62
  if (strippedFilePath.startsWith(TRIMMING_DOTS)) {
73
63
  trimLength = TRIMMING_DOTS.length;
74
64
  } else if (strippedFilePath.startsWith(relativePathHead)) {
@@ -76,7 +66,6 @@ export const highlight = (rawPath, filePath, pattern) => {
76
66
  } else {
77
67
  trimLength = 0;
78
68
  }
79
-
80
69
  const start = match.index - offset;
81
70
  const end = start + match[0].length;
82
71
  return colorize(strippedFilePath, Math.max(start, 0), Math.max(end, trimLength));
@@ -84,36 +73,28 @@ export const highlight = (rawPath, filePath, pattern) => {
84
73
  export const formatTestNameByPattern = (testName, pattern, width) => {
85
74
  const inlineTestName = testName.replace(/(\r\n|\n|\r)/gm, ENTER);
86
75
  let regexp;
87
-
88
76
  try {
89
77
  regexp = new RegExp(pattern, 'i');
90
78
  } catch (e) {
91
79
  return chalk.dim(inlineTestName);
92
80
  }
93
-
94
81
  const match = inlineTestName.match(regexp);
95
-
96
82
  if (!match || match.index == null) {
97
83
  return chalk.dim(inlineTestName);
98
84
  }
99
-
100
85
  const startPatternIndex = Math.max(match.index, 0);
101
86
  const endPatternIndex = startPatternIndex + match[0].length;
102
87
  const testNameFitsInTerminal = inlineTestName.length <= width;
103
-
104
88
  if (testNameFitsInTerminal) {
105
89
  return colorize(inlineTestName, startPatternIndex, endPatternIndex);
106
90
  }
107
-
108
91
  const numberOfTruncatedChars = TRIMMING_DOTS.length + inlineTestName.length - width;
109
92
  const end = Math.max(endPatternIndex - numberOfTruncatedChars, 0);
110
93
  const truncatedTestName = inlineTestName.slice(numberOfTruncatedChars);
111
94
  const shouldHighlightDots = startPatternIndex <= numberOfTruncatedChars;
112
-
113
95
  if (shouldHighlightDots) {
114
96
  return colorize(TRIMMING_DOTS + truncatedTestName, 0, end + TRIMMING_DOTS.length);
115
97
  }
116
-
117
98
  const start = startPatternIndex - numberOfTruncatedChars;
118
99
  return colorize(TRIMMING_DOTS + truncatedTestName, start + TRIMMING_DOTS.length, end + TRIMMING_DOTS.length);
119
100
  };
@@ -121,6 +102,5 @@ export const removeTrimmingDots = value => {
121
102
  if (value.startsWith(TRIMMING_DOTS)) {
122
103
  return value.slice(TRIMMING_DOTS.length);
123
104
  }
124
-
125
105
  return value;
126
106
  };
@@ -15,7 +15,6 @@ export default class TestNamePlugin {
15
15
  prompt: config.prompt || 'filter by a test name regex pattern'
16
16
  };
17
17
  }
18
-
19
18
  apply(jestHooks) {
20
19
  jestHooks.onTestRunComplete(({
21
20
  testResults
@@ -23,11 +22,9 @@ export default class TestNamePlugin {
23
22
  this._testResults = testResults;
24
23
  });
25
24
  }
26
-
27
25
  onKey(key) {
28
26
  this._prompt.put(key);
29
27
  }
30
-
31
28
  run(globalConfig, updateConfigAndRun) {
32
29
  const p = new TestNamePatternPrompt(this._stdout, this._prompt);
33
30
  p.updateCachedTestResults(this._testResults);
@@ -41,9 +38,7 @@ export default class TestNamePlugin {
41
38
  }, rej);
42
39
  });
43
40
  }
44
-
45
41
  getUsageInfo() {
46
42
  return this._usageInfo;
47
43
  }
48
-
49
44
  }
@@ -12,24 +12,18 @@ export default class TestNamePatternPrompt extends PatternPrompt {
12
12
  this._cachedTestResults = [];
13
13
  this._offset = -1;
14
14
  }
15
-
16
15
  _onChange(pattern, options) {
17
16
  super._onChange(pattern, options);
18
-
19
17
  this._offset = options.offset;
20
-
21
18
  this._printTypeahead(pattern, options);
22
19
  }
23
-
24
20
  _printTypeahead(pattern, options) {
25
21
  const matchedTests = this._getMatchedTests(pattern);
26
-
27
22
  const total = matchedTests.length;
28
23
  const pipe = this._pipe;
29
24
  const prompt = this._prompt;
30
25
  printPatternCaret(pattern, pipe);
31
26
  pipe.write(ansiEscapes.cursorLeft);
32
-
33
27
  if (pattern) {
34
28
  printPatternMatches(total, 'test', pipe, ` from ${chalk.yellow('cached')} test suites`);
35
29
  const width = getTerminalWidth(pipe);
@@ -40,26 +34,21 @@ export default class TestNamePatternPrompt extends PatternPrompt {
40
34
  } = scroll(total, options);
41
35
  prompt.setPromptLength(total);
42
36
  matchedTests.slice(start, end).map(name => formatTestNameByPattern(name, pattern, width - 4)).map((item, i) => formatTypeaheadSelection(item, i, index, prompt)).forEach(item => printTypeaheadItem(item, pipe));
43
-
44
37
  if (total > end) {
45
38
  printMore('test', pipe, total - end);
46
39
  }
47
40
  } else {
48
41
  printStartTyping('test name', pipe);
49
42
  }
50
-
51
43
  printRestoredPatternCaret(pattern, this._currentUsageRows, pipe);
52
44
  }
53
-
54
45
  _getMatchedTests(pattern) {
55
46
  let regex;
56
-
57
47
  try {
58
48
  regex = new RegExp(pattern, 'i');
59
49
  } catch (e) {
60
50
  return [];
61
51
  }
62
-
63
52
  return this._cachedTestResults.reduce((matchedTests, {
64
53
  testResults
65
54
  }) => {
@@ -70,11 +59,9 @@ export default class TestNamePatternPrompt extends PatternPrompt {
70
59
  }) => fullName));
71
60
  }, []);
72
61
  }
73
-
74
62
  updateCachedTestResults(testResults = []) {
75
63
  this._cachedTestResults = testResults;
76
64
  }
77
-
78
65
  run(onSuccess, onCancel, options) {
79
66
  super.run(value => {
80
67
  const preparedPattern = escapeStrForRegex(removeTrimmingDots(value));
@@ -82,5 +69,4 @@ export default class TestNamePatternPrompt extends PatternPrompt {
82
69
  onSuccess(useExactMatch ? `^${preparedPattern}$` : preparedPattern);
83
70
  }, onCancel, options);
84
71
  }
85
-
86
72
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jest-watch-typeahead",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "main": "build/index.js",
5
5
  "exports": {
6
6
  ".": "./build/index.js",
@@ -32,11 +32,11 @@
32
32
  "typecheck": "yarn tsc -p ."
33
33
  },
34
34
  "dependencies": {
35
- "ansi-escapes": "^5.0.0",
35
+ "ansi-escapes": "^6.0.0",
36
36
  "chalk": "^4.0.0",
37
37
  "jest-regex-util": "^29.0.0",
38
38
  "jest-watcher": "^29.0.0",
39
- "slash": "^4.0.0",
39
+ "slash": "^5.0.0",
40
40
  "string-length": "^5.0.1",
41
41
  "strip-ansi": "^7.0.1"
42
42
  },
@@ -49,7 +49,7 @@
49
49
  "@jest/types": "^29.0.0",
50
50
  "@semantic-release/changelog": "^6.0.1",
51
51
  "@semantic-release/git": "^10.0.1",
52
- "@types/node": "^16.0.0",
52
+ "@types/node": "^14.0.0",
53
53
  "@typescript-eslint/eslint-plugin": "^5.0.0",
54
54
  "@typescript-eslint/parser": "^5.0.0",
55
55
  "babel-jest": "^29.0.0",
@@ -109,5 +109,8 @@
109
109
  "@semantic-release/github"
110
110
  ]
111
111
  },
112
- "packageManager": "yarn@3.2.3"
112
+ "packageManager": "yarn@3.3.0",
113
+ "resolutions": {
114
+ "ansi-escapes/type-fest": "^3.0.0"
115
+ }
113
116
  }