Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor and improve watch mode with testPathPattern and testNamePattern #2568

Merged
merged 31 commits into from
Feb 14, 2017
Merged

Refactor and improve watch mode with testPathPattern and testNamePattern #2568

merged 31 commits into from
Feb 14, 2017

Conversation

zouxuoz
Copy link
Contributor

@zouxuoz zouxuoz commented Jan 11, 2017

Summary

Resolve #1860 #2546

Tasks

  • refactor user input in watch mode;
  • use args.testPathPattern instead of 'args._' in watch mode;
  • add ability to pass and useargs.testNamePattern in watch mode;

Test plan

Works on local machine and added unit tests are passed.

Preview

jan-13-2017 23-57-37

@codecov-io
Copy link

codecov-io commented Jan 12, 2017

Codecov Report

Merging #2568 into master will increase coverage by 0.62%.
The diff coverage is 90.77%.

@@            Coverage Diff             @@
##           master    #2568      +/-   ##
==========================================
+ Coverage   67.12%   67.74%   +0.62%     
==========================================
  Files         142      146       +4     
  Lines        5126     5237     +111     
==========================================
+ Hits         3441     3548     +107     
- Misses       1685     1689       +4
Impacted Files Coverage Δ
packages/jest-cli/src/constants.js 100% <ø> (ø)
packages/jest-cli/src/runJest.js 0% <ø> (ø)
packages/jest-jasmine2/src/index.js 0% <ø> (ø)
packages/jest-cli/src/lib/colorize.js 100% <100%> (ø)
packages/jest-cli/src/lib/setState.js 95.45% <100%> (ø)
packages/jest-cli/src/lib/highlight.js 96.15% <66.66%> (-0.4%)
packages/jest-cli/src/watch.js 75% <75.86%> (+0.86%)
...ckages/jest-cli/src/lib/formatTestNameByPattern.js 90.9% <90.9%> (ø)
packages/jest-cli/src/lib/Prompt.js 93.1% <93.1%> (ø)
packages/jest-cli/src/TestNamePatternPrompt.js 94.33% <94.33%> (ø)
... and 7 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 8c17c0f...43ab817. Read the comment docs.

Copy link
Contributor

@rogeliog rogeliog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is awesome that you have already rebased on top of the typeahead 😄 I'll take a deeper look later, but I left some early feedback

onlyChanged: false,
watch: false,
watchAll: true,
});
});

it('Pressing "T" enters testname pattern mode', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can update these tests to look similar to https://github.com/facebook/jest/blob/master/packages/jest-cli/src/__tests__/watch-pattern-mode-test.js#L86 in those tests we heavily use snapshots and they give us some nice insight of how the state updates over time :)

delete argv.testPathPattern;
delete argv.testNamePattern;

if (options && options.onlyChanged) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can use a the default param syntax to prevent all of the options &&

@@ -37,7 +37,7 @@ const getTestSummary = (
: '';

const nameInfo = argv.testNamePattern
? chalk.dim(' with tests matching ') + `"${argv.testNamePattern}"`
? chalk.dim(' with tests matching ') + `"/${argv.testNamePattern}/"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why these '/' is so that it looks like a RegExp?

});
let currentPattern = '';

let isEnteringString = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As pattern mode becomes more and more complex it seems that we need to start extracting all of this logic out of watch.js.. so that the pattern mode and typeahead stuff can scale and be maintained in the future.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yay extract more. Love that this code is getting so solid.

@cpojer
Copy link
Member

cpojer commented Jan 27, 2017

@zouxuoz are you getting back to this?

@zouxuoz
Copy link
Contributor Author

zouxuoz commented Jan 27, 2017

@cpojer yes, I will do at the weekend

@zouxuoz
Copy link
Contributor Author

zouxuoz commented Jan 30, 2017

TO DO

  • Separate prompt patterns logic and watch mode logic
  • Separate test path pattern mode logic and watch mod
  • Return test name pattern mode

@rogeliog
Copy link
Contributor

rogeliog commented Feb 1, 2017

@zouxuoz Sorry that I haven't reviewed your latest changes, I've been really busy but I'll try to get to it as soon as possible 😄

@zouxuoz
Copy link
Contributor Author

zouxuoz commented Feb 1, 2017

@rogeliog no problem. I'm ping you when PR is ready for review 😉

@cpojer
Copy link
Member

cpojer commented Feb 7, 2017

Hey! What's the status of this? @zouxuoz is this ready for review? I'd like to get it in for Jest 19.

Also, as a follow-up, it would be cool to cache the test names after the first run so we can also use pattern mode for this after the initial run!

Copy link
Contributor

@rogeliog rogeliog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this :)

I'm a bit confused, this does not add any testNamePattern logic right? It is just the refactor

pipe: stream$Writable | tty$WriteStream,
promptController: PromptController,
) => {
class TestPathPatternModeController {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just exporting the class directly

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed.

pipe.write(ansiEscapes.cursorShow);

promptController.prompt(
this.onChange.bind(this),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can bind this in the constructor or use class property syntax so that we don't have to re-bind it every time that it runs.

bind in constructor

constructor() {
  this.onChange = this.onChange.bind(this);
}

class property

onChange = () => {
// ...content
}


promptController.prompt(jest.fn(), onSuccess, jest.fn());

promptController.put('74');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could extract this to a KEYS object at the top level of this file, this should make the tests easier to follow in the future :)

let {KEYS} = require('../../constants');
KEYS = Object.assign({}, KEYS, {
  E: '65',
  S: '73',
  T: '74',
}
promptController.put(KEYS.T);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed!

@zouxuoz
Copy link
Contributor Author

zouxuoz commented Feb 8, 2017

@rogeliog Thanks for review. @cpojer I'm fix it and send changes with testNamePattern mode in the next few days.

@zouxuoz
Copy link
Contributor Author

zouxuoz commented Feb 8, 2017

@rogeliog @cpojer please give me feedback about UX of new features, while I'm refactoring code, and writing tests for that 😉

feb-08-2017 13-40-55

@thymikee
Copy link
Collaborator

thymikee commented Feb 8, 2017

This is kickass.

@cpojer
Copy link
Member

cpojer commented Feb 8, 2017

OMG this is exactly what I was thinking of. Can we maybe have the name of the test file there as well?

transform-test.js > it will work
transform-test.js > it tests this feature

and if there is ambiguity (two files with the same name), do:

.../jest-runtime/transform-test.js > it will work
.../jest-haste-map/transform-test.js > it will work too

what do you think? We have a way to shorten path names, we can simply re-use it.

? chalk.dim(' \u203A Press ') + 'o' + chalk.dim(' to only run tests related to changed files.')
: null,
snapshotFailure
? chalk.dim(' \u203A Press ') + 'u' + chalk.dim(' to update failing snapshots.')
: null,
chalk.dim(' \u203A Press ') + 'p' + chalk.dim(' to filter by a filename regex pattern.'),
chalk.dim(' \u203A Press ') + 't' + chalk.dim(' to filter by a testname regex pattern.'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we do "test name regex pattern"?

@@ -167,21 +150,54 @@ const watch = (
startRun({updateSnapshot: true});
break;
case KEYS.A:
setWatchMode(argv, 'watchAll');
setWatchMode(argv, 'watchAll', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we rename this function to "setWatchState", or given that it is inside of "watch.js", simply call it "setState"? I think that makes more sense.

@zouxuoz
Copy link
Contributor Author

zouxuoz commented Feb 8, 2017

@cpojer it's a good suggestion, but what it will look like if a single file has many of tests?

.../jest-runtime/transform-test.js > it will work 1
.../jest-runtime/transform-test.js > it will work 2
.../jest-runtime/transform-test.js > it will work 3
.../jest-runtime/transform-test.js > it will work 4
.../jest-runtime/transform-test.js > it will work 5
.../jest-haste-map/transform-test.js > it will work too 1
.../jest-haste-map/transform-test.js > it will work too 2
.../jest-haste-map/transform-test.js > it will work too 3

Filenames occupy a lot of space, may be we can group test names by filename?

@cpojer
Copy link
Member

cpojer commented Feb 8, 2017

Hmm.. yeah you are right. How does this feel:

  • If only a single file matches, don't show the filename
  • If multiple file names match, show only the filename
  • If multiple file names have the same name, show the file name and path

?

pipe.write(ansiEscapes.clearScreen);
pipe.write(usage(argv, hasSnapshotFailure));
pipe.write(ansiEscapes.cursorShow);
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we factor this function out? We have some duplication here.

testPathPattern: argv.testPathPattern
|| argv._ instanceof Array
? argv._.join('|')
: '',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, code style:

testPathPattern: argv.testPathPattern || Array.isArray(argv._)
  ? argv._.join('|')
  : '',

do you also want to check for .length of the array? I guess it produces the same output here.

Don't use instanceof Array, Array.isArray is much safer.

@@ -14,7 +14,7 @@ const buildTestPathPatternInfo = require('./buildTestPathPatternInfo');
const setWatchMode = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As said, let's rename this file to setState.

@@ -14,7 +14,7 @@ const buildTestPathPatternInfo = require('./buildTestPathPatternInfo');
const setWatchMode = (
argv: Object,
mode: 'watch' | 'watchAll',
options?: Object,
options?: Object = {},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this won't work on all versions of node 4, let's not use default args please :)

expect(onSuccess).toHaveBeenCalledWith('test');
});

it('should calls handler on cancel prompt', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get rid of the "should" here :)

this.value.slice(0, -1)
:
this.value + char
;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code style:

this.value = key === KEYS.BACKSPACE
  ? this.value.slice(0, -1)
  : this.value + char;

}

put(
key: string
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comma at the end.


const {KEYS} = require('../constants');

class PromptController {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't like the word "Controller" in code. Can we simply call this "Prompt" here and everywhere else?

const {KEYS} = require('../constants');

class PromptController {
entering: boolean;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's call this "_isEntering". Please add a _ to all fields that are supposed to be private.

onSuccess: Function;
onCancel: Function;

prompt(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about "prompt.enter()"?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or "prompt.start"?

@zouxuoz
Copy link
Contributor Author

zouxuoz commented Feb 11, 2017

@cpojer ready for review

Copy link
Contributor

@rogeliog rogeliog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is looking really good!

const colorize = require('./colorize');

const DOTS = '...';
const ENTER = '⏎';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we also need to check for stuff like \n or \r\n?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and \r 🙄 I've fixed it.

@rogeliog
Copy link
Contributor

I'm seeing an issue where the the pattern matches tests but they don't execute

test-name-bug

@rogeliog
Copy link
Contributor

I'm not sure why but I'm getting a MaxListenersExceededWarning that shows up at the bottom of the runner. Might be unrelated.

flickery

@zouxuoz
Copy link
Contributor Author

zouxuoz commented Feb 12, 2017

@rogeliog I've fixed the first issue and reproduced the second issue, but it's bug from the master branch, not this PR. I'm trying to fix it, but I think we can do it in another PR.

@cpojer cpojer merged commit 908f066 into jestjs:master Feb 14, 2017
@cpojer
Copy link
Member

cpojer commented Feb 14, 2017

This is awesome work @zouxuoz. There are definitely ways we can make this even better but I think it is ready to be merged. We can do small follow-ups to make this really solid – looking forward to more of your contributions. If you don't mind, please send me your email address: cpojer@fb.com so I can invite you to our jest-core chat.

skovhus pushed a commit to skovhus/jest that referenced this pull request Apr 29, 2017
…ern (jestjs#2568)

* Separate prompt patterns logic and watch mode logic

* Separate pathname pattern mode logic and watch mode

* Using testPathPattern for path pattern mode instead of _ args

* Add initial testname pattern mode

* Cache testnames for pattern mode

* fix direct exporting

* fix re-bind for on change handler

* fix keys constants in tests

* fix testname whitespace

* rename setWatchMode to setState

* refactor cancel pattern mode function

* fix code style

* rid of default params in functions

* rid of should in tests

* fix code style

* fix comma

* rename prompt files

* fix private fields

* rename prompt to enter

* fix comma

* fix comma and default param

* fix code style

* fix testname whitespace

* refactor cache test names

* Add tests for test name pattern mode

* Add prefix with test file path for test name pattern mode

* Move colorize to separate file

* Update prompt on resize terminal

* Better output for test name pattern mode

* Ignore case for testNamePattern

* Replace all types of the line breaks for test names in watch pattern mode
tushardhole pushed a commit to tushardhole/jest that referenced this pull request Aug 21, 2017
…ern (jestjs#2568)

* Separate prompt patterns logic and watch mode logic

* Separate pathname pattern mode logic and watch mode

* Using testPathPattern for path pattern mode instead of _ args

* Add initial testname pattern mode

* Cache testnames for pattern mode

* fix direct exporting

* fix re-bind for on change handler

* fix keys constants in tests

* fix testname whitespace

* rename setWatchMode to setState

* refactor cancel pattern mode function

* fix code style

* rid of default params in functions

* rid of should in tests

* fix code style

* fix comma

* rename prompt files

* fix private fields

* rename prompt to enter

* fix comma

* fix comma and default param

* fix code style

* fix testname whitespace

* refactor cache test names

* Add tests for test name pattern mode

* Add prefix with test file path for test name pattern mode

* Move colorize to separate file

* Update prompt on resize terminal

* Better output for test name pattern mode

* Ignore case for testNamePattern

* Replace all types of the line breaks for test names in watch pattern mode
@github-actions
Copy link

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 13, 2021
This pull request was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

testNamePattern in watch mode
6 participants