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

Only match relative paths when specifying paths #12519

Merged
merged 23 commits into from
Oct 3, 2023
Merged

Only match relative paths when specifying paths #12519

merged 23 commits into from
Oct 3, 2023

Conversation

brandon-leapyear
Copy link
Contributor

@brandon-leapyear brandon-leapyear commented Mar 1, 2022

Summary

Fixes #10746.

Adds a new TestPathPatterns class which consolidates all the logic related to checking if a test path matches user-specified patterns. This class was necessary to add because previously, GlobalConfig just stored the final regex in testPathPattern, which would be shown in output like:

Ran tests matching pattern: <testPathPattern regex>

But with this change, the regex could get rather complicated; e.g. if a user ran jest foo bar in /Users/myuser/github/my-project, the output would be:

Ran tests matching pattern: /\/Users\/myuser\/github\/my-project\/(.*)foo|\/Users\/myuser\/github\/my-project\/(.*)bar/

So we need to separate the notion of "how to match paths against patterns" from "how to show the patterns to the user" in the config. So instead of the config storing the final regex, it now stores the original list of patterns specified and then builds the regex on demand; in fact, the reality that TestPathPatterns uses a regex is now an implementation detail (it pretty much only exposes the isMatch function as the public entrypoint), so if the pattern-matching logic needs to be more complex than a regex can handle, and we want to just do a naive

for (const pattern of self.patterns) {
  if (isRegex(pattern) && pattern.test(path)) {
    return true
  }
  if (isOtherComplicatedPattern(pattern) && pattern.matches(path)) {
    return true
  }
}
return false

we're now free to do so!

Commit explanation

  • Pure refactoring + simplification
    • Factor out toString() call
    • Remove redundant 'globalConfig.testPathPattern != null' check
  • Add + use TestPathPatterns
    • Consolidate testPathPatterns logic
    • Return TestPathPatterns in normalize helper
    • Store parsed patterns in global config
    • Change normalize tests to test testPathPatterns
    • Replace testPathPatternToRegExp with TestPathPatterns
    • Update testPathPatterns in updateGlobalConfig
    • Update docs + tests to use globalConfig.testPathPatterns
    • Replace remaining usages of globalConfig.testPathPattern
    • Fix tests using partial GlobalConfigs
    • Remove testPathPattern from GlobalConfig
  • Fix relative path issue
    • Add failing tests for matching outside relative path
    • Only match within relative path
  • Update CHANGELOG

Test plan

Running yarn jest --listTests user before this branch listed all tests on a Mac, where everything is under /Users/<username/. After this branch, it only shows the users.test.js tests

@brandon-leapyear brandon-leapyear changed the title Only match relative paths when specifying paths [WIP] Only match relative paths when specifying paths Mar 1, 2022
@SimenB SimenB marked this pull request as draft March 1, 2022 07:28
@SimenB
Copy link
Member

SimenB commented Mar 1, 2022

Oh, looks like a pretty large refactor! Ping me when you have something semi-working and I'll take a look! 🙂

@brandon-leapyear
Copy link
Contributor Author

@SimenB looks ready to go!

@SimenB
Copy link
Member

SimenB commented Mar 5, 2022

This disconnects --testPathPattern from testPathPattern in config, any particular reason for that? I think it's confusing those are different

@brandon-leapyear brandon-leapyear changed the title [WIP] Only match relative paths when specifying paths Only match relative paths when specifying paths Mar 5, 2022
@brandon-leapyear
Copy link
Contributor Author

@SimenB how's that?

@github-actions
Copy link

github-actions bot commented Jun 3, 2022

This PR is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 30 days.

@github-actions github-actions bot added the Stale label Jun 3, 2022
@brandonchinn178
Copy link
Contributor

@SimenB ping

@github-actions github-actions bot removed the Stale label Jun 3, 2022
@github-actions
Copy link

github-actions bot commented Sep 1, 2022

This PR is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 30 days.

@github-actions github-actions bot added the Stale label Sep 1, 2022
@brandonchinn178
Copy link
Contributor

@SimenB

@github-actions github-actions bot removed the Stale label Sep 1, 2022
@github-actions
Copy link

github-actions bot commented Dec 1, 2022

This PR is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 30 days.

@github-actions github-actions bot added the Stale label Dec 1, 2022
@brandon-leapyear
Copy link
Contributor Author

Not stale

@github-actions github-actions bot removed the Stale label Dec 1, 2022
@SimenB SimenB added this to the Jest 30 milestone Jan 1, 2023
@SimenB SimenB added the Pinned label Jan 1, 2023
@legobeat
Copy link

@brandon-leapyear @SimenB needs rebase on main

@netlify
Copy link

netlify bot commented Apr 26, 2023

Deploy Preview for jestjs ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 09aed7d
🔍 Latest deploy log https://app.netlify.com/sites/jestjs/deploys/651ab6141b358d00073e2b83
😎 Deploy Preview https://deploy-preview-12519--jestjs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Apr 26, 2023

CLA Signed

The committers listed above are authorized under a signed CLA.

@brandonchinn178
Copy link
Contributor

@legobeat done

@SimenB
Copy link
Member

SimenB commented Sep 20, 2023

Hey @brandon-leapyear! Finally ready to land this - could I bother you with one last rebase? 🙏

@SimenB
Copy link
Member

SimenB commented Sep 21, 2023

Thanks! There's some CI errors - could you take a look?

@brandonchinn178
Copy link
Contributor

@SimenB Updated!

Copy link
Member

@SimenB SimenB left a comment

Choose a reason for hiding this comment

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

just some quick feedback (currently travelling) - overall it looks really good!

CHANGELOG.md Show resolved Hide resolved
* for simplicity.
*/
toPretty(): string {
const regex = this.patterns.map(p => p.replace(/\//g, '\\/')).join('|');
Copy link
Member

Choose a reason for hiding this comment

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

why do we want the escape characters? for copy paste?

I'm not sure I find it very "pretty" 😅

Copy link
Contributor

Choose a reason for hiding this comment

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

ah I was trying to imitate what the original code was doing. Instead of doing this manually, I really should just return this.regex.toString().

And, sure, maybe it's not "pretty" anymore, so I'll rename the function to toString (really it's just rendering the patterns back to a string to show to the user)

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah that's right, I can't do this.regex.toString() because the regex now contains extra information about the root directory:

# Original message
Ran all test suites matching /a\/b|c\/d/i.

# TestPathPatterns.toPretty()
Ran all test suites matching /a\/b|c\/d/i.

# TestPathPatterns.regex.toString()
Ran all test suites matching /\/(.*)?a\/b|\/(.*)?c\/d/i.

It's "pretty" in the sense that it's not literally the regex that we're using to match tests. If your main concern is the name of the function, I'm happy to rename it to something else, I just can't think of a better name

Copy link
Member

@SimenB SimenB Sep 27, 2023

Choose a reason for hiding this comment

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

My main "objection" is that I find the escaped path separators to be harder to read than the original patterns

image

Is just more characters to ignore in order to read the pattern.

I guess I understand it's to render the regex flag, but still

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh ok so currently, jest renders the "no tests found" and the "ran tests matching" messages differently:

$ jest foo/bar bar/baz --testPattern x/a

Pattern: foo/bar|bar/baz|x/a - 0 matches

Ran all test suites matching /foo\/bar|bar\/baz|x\/a/i.
  1. Should these messages render the pattern the same way? Or should it be the case that the no-matches message shows a "pretty" version, and the tests-found message shows the actual regex?
  2. If they should be rendered the same way, which way should they be rendered?

Copy link
Member

Choose a reason for hiding this comment

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

I'd personally prefer them to render without escape characters - it's just easier to read (same as we change backslashes to forward slashes for windows in reporters and such). And consistency is always good! 🙂

So 1. yes - 2. Pattern.

Copy link
Contributor

@brandonchinn178 brandonchinn178 Sep 30, 2023

Choose a reason for hiding this comment

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

Updated: 3c22ef3

packages/jest-util/src/index.ts Show resolved Hide resolved
packages/jest-util/src/TestPathPatterns.ts Outdated Show resolved Hide resolved
Copy link
Member

@SimenB SimenB left a comment

Choose a reason for hiding this comment

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

wonderful, thank you so much for your patience!

I think my only comment at this moment in time would be that it'd be nice to avoid reparsing the regexes all the time in the new TestPathPatterns class we instantiate all over the place. But that is by no means a blocker, so if it proves hard, I'm happy to merge this as-is 🙂

@brandonchinn178
Copy link
Contributor

I would weakly prefer merging as-is, mostly because I'm not sure where to put the initialized TestPathPatterns in a place reachable by everything. The obvious thing is to store it in GlobalConfig, but it seems like jest-util depends on @jest/types, so I can't pull it into there. And I'm not sure the entire TestPathPatterns logic belongs in @jest/types. If you could provide some guidance on how to go about this, I'm happy to, but I think it would equally fine to merge this already-large PR and do this in another PR?

@SimenB SimenB merged commit 41133b5 into jestjs:main Oct 3, 2023
60 checks passed
@brandonchinn178 brandonchinn178 deleted the chinn/relative-paths branch October 4, 2023 01:01
Copy link

github-actions bot commented Nov 4, 2023

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 Nov 4, 2023
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.

Passing in test files to CLI should be matched against relative path
5 participants