jest-watch-typeahead 2.2.0 → 2.2.1

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.
@@ -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
  }