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

Updates babel-jest resolution #5932

Merged
merged 2 commits into from
Apr 11, 2018
Merged

Conversation

arcanis
Copy link
Contributor

@arcanis arcanis commented Apr 5, 2018

Summary

The babel-jest default transform is currently located through Resolver.findNodeModules. This has the inconvenient that when using a custom resolver, this new custom resolver will be completely bypassed.

Given that require.resolve is the standard and safe way to obtain the requirable path to a package, I think we should use it whenever possible, at least until the custom resolver has been properly setup (ie after the config has been normalized).

Two notes:

  • This might be a slight breaking change if users were specifying different version of babel-jest than the default. I'm not sure it's often the case, so it doesn't feel too problematic.

  • The regenerator package is still located using Resolver.findNodeModules. It would be nice to fix this as well, but since this package is meant to be added by the user, only the user can use require.resolve to obtain its path (we can't use process.main because it points to the Jest cli). Since it's quite more complex, it can be done later on.

Test plan

I've updated the tests to match the behavior (ie mostly checked that the resulting configuration was matching whatever is returned by require.resolve rather than an hardcoded node_modules/babel-jest).

@arcanis
Copy link
Contributor Author

arcanis commented Apr 5, 2018

cc @mjesun @cpojer

@@ -684,7 +684,9 @@ describe('babel-jest', () => {
beforeEach(() => {
Resolver = require('jest-resolve');
Resolver.findNodeModule = jest.fn(
name => path.sep + 'node_modules' + path.sep + name,
name => {
Copy link
Member

Choose a reason for hiding this comment

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

can you remove the curly brace + return again? Doesn't seem necessary here and Jest's code style is to not use these when it's a single expression.

@@ -684,7 +684,9 @@ describe('babel-jest', () => {
beforeEach(() => {
Resolver = require('jest-resolve');
Resolver.findNodeModule = jest.fn(
name => path.sep + 'node_modules' + path.sep + name,
name => {
return name.indexOf('babel-jest') === -1 ? path.sep + 'node_modules' + path.sep + name : name;
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this be name === 'babel-jest'?

@@ -113,24 +113,20 @@ const setupBabelJest = (options: InitialOptions) => {
});

if (customJSPattern) {
const jsTransformer = Resolver.findNodeModule(
Copy link
Member

Choose a reason for hiding this comment

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

You are removing the resolution for packages that are not babel-jest, like ts-jest or ./my-custom-file or my-custom-transformer. You still need to support those as well.

Copy link
Contributor Author

@arcanis arcanis Apr 5, 2018

Choose a reason for hiding this comment

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

Hm, I see what you mean. Do you think it would be reasonable to have the same findNodeModule call as a fallback to avoid breaking the existing, but encourage people to use require.resolve in their configuration?

module.exports = {
  transform: {
    "*.ts": require.resolve('ts-jest')
  }
};

An issue is that it wouldn't work as-is in the package.json configuration, since functions can't be called here, so it would have to be kept inside a js configuration file.

Copy link
Contributor Author

@arcanis arcanis Apr 5, 2018

Choose a reason for hiding this comment

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

An alternative would be to defer resolving those paths until after the configuration has been completed, and then use the right resolver - but the same issue will occur for the resolver option, which ironically will need to be manually resolved by the user through require.resolve.

Copy link
Member

Choose a reason for hiding this comment

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

What if in Jest we call Resolver.findNodeModule(value). If it returns null, we call Resolver.findNodeModule(require.resolve(value)) (or just require.resolve(value) itself if possible). That way it doesn't affect users.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But then it will resolve them relative to jest-config, not the user project. So ts-jest for example could fail because it would not be listed as a dependency of jest-config (whereas a require.resolve from the configuration file would always work, because the configuration file would be in the toplevel project).

Copy link
Member

Choose a reason for hiding this comment

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

Oh right, yeah this is a bit of a bummer :( I'd prefer not to demand people to rewrite their config with JS.

Copy link
Contributor Author

@arcanis arcanis Apr 6, 2018

Choose a reason for hiding this comment

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

Actually I just read the code again and I don't think this PR prevents external transformers from working - setupBabelJest is only used to detect babel jest and, if it can be found, automatically inject regenerator. Any other loader will be resolved and required later, through the regular resolver (cf here).

@cpojer
Copy link
Member

cpojer commented Apr 5, 2018

I left a few comments. I think this will break resolution of custom transformers which we'll need to support. Can you fix that?

Copy link
Member

@cpojer cpojer left a comment

Choose a reason for hiding this comment

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

Yes, you are right. Assuming all tests are passing, this is looks good to me actually :) Thanks!

@arcanis arcanis force-pushed the babel-jest-resolution branch 2 times, most recently from d2681a8 to d6d9fc8 Compare April 10, 2018 10:21
@arcanis
Copy link
Contributor Author

arcanis commented Apr 10, 2018

The failing tests are driving me crazy - if I update the snapshots they break in node 6, but if I don't they break in 8/9 :/ They don't look related to my diff either ... what do you think?

@SimenB
Copy link
Member

SimenB commented Apr 10, 2018

Are you rebased on master? We use sourcemaps (provided by babel through babel-jest) to make the stacks correct, seems like it's off somehow on different nodes?

@arcanis
Copy link
Contributor Author

arcanis commented Apr 10, 2018

@SimenB Yep, rebased on master. My theory is that the current codebase has an issue with Node 8/9 that was hidden in this test until now. The problem is on the following condition: https://github.com/facebook/jest/pull/5932/files#diff-8ee186ad0e07dceb57c11f7c7b5d072aR121

Before my commit, Jest was sometimes failing to locate babel-jest, probably because the tests were running inside a temporary directory. Due to this, the transpilation wasn't actually being ran at all, and the correct results were being returned on Node 8/9.

Starting from my commit, babel-jest is now always resolved (by using the one that Jest depends on), so the transpilation always run, and we apparently always hit the bug where the sourcemaps aren't correctly computed on Node 8/9.

What do you think?

@codecov-io
Copy link

Codecov Report

Merging #5932 into master will increase coverage by 0.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #5932      +/-   ##
==========================================
+ Coverage   64.33%   64.34%   +0.01%     
==========================================
  Files         217      217              
  Lines        8286     8286              
  Branches        4        3       -1     
==========================================
+ Hits         5331     5332       +1     
+ Misses       2954     2953       -1     
  Partials        1        1
Impacted Files Coverage Δ
packages/jest-config/src/normalize.js 94.04% <100%> (+0.02%) ⬆️
packages/jest-environment-jsdom/src/index.js 40% <0%> (+0.97%) ⬆️

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 1a51672...76adee3. Read the comment docs.

@SimenB
Copy link
Member

SimenB commented Apr 10, 2018

It's green now 🤷‍♂️

Edit: ah, you removed the line and column. Not sure if that's the correct fix... (Might be, have to give it a thought or two)

@arcanis
Copy link
Contributor Author

arcanis commented Apr 10, 2018 via email

@SimenB
Copy link
Member

SimenB commented Apr 10, 2018

I'm not comfortable moving away from working sourcemaps, even though they might be working through a happy accident (working by accident is better than not working :D)

If you can tell me how the current approach is wrong with regards to sourcemaps, I'll be happy to remove my objection (to the degree it matters)

@arcanis
Copy link
Contributor Author

arcanis commented Apr 10, 2018

@SimenB this PR doesn't actually break the sourcemaps - they're already broken (to some extent). To reproduce, just create a new project with 23.0.0-alpha.5, add a testfile containing the following code, and run it. It will crash with an invalid column on Node 9 (but works on Node 6), printing 1 instead of 5:

    it('it', () => {});
    it('it foo');
    test('test bar');

I think the issue simply comes from babel just keeping track of the rows instead of rows+columns.

@SimenB
Copy link
Member

SimenB commented Apr 10, 2018

Is it just broken in the alphas (meaning master) or in the stable 22 releases as well?

@paxa1980

This comment has been minimized.

@arcanis
Copy link
Contributor Author

arcanis commented Apr 10, 2018

@SimenB Not sure. Before the 23.0.0, not entering the test definition wasn't a hard error (it was just skipping the test altogether), and regular errors thrown from within the test definition don't seem to suffer from this issue in both 22.X and 23.X.

@SimenB
Copy link
Member

SimenB commented Apr 11, 2018

Might mess up #5889 as well, then

@arcanis
Copy link
Contributor Author

arcanis commented Apr 11, 2018 via email

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.

If this does mess up the stack traces, we might want to revert. But the change itself is nice, so I think we should try 🙂

@arcanis
Copy link
Contributor Author

arcanis commented Apr 11, 2018

👍

@arcanis arcanis merged commit 90810b1 into jestjs:master Apr 11, 2018
@SimenB
Copy link
Member

SimenB commented Apr 13, 2018

This does indeed mess up #5889 (I've rebased it), but just for the globals test (same one you had to strip out the line and column info in this PR). I think I'll have to dig into why this change makes us lose column information

@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 12, 2021
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.

6 participants