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

babel-jest can't handle template strings within a require statement in with --watch flag #7511

Closed
thisissami opened this issue Dec 13, 2018 · 14 comments · Fixed by #9303
Closed
Labels

Comments

@thisissami
Copy link

thisissami commented Dec 13, 2018

🐛 Bug Report

When running require within a block of code that contains a template string (e.g. require(images/${imageURL})), babel-jest fails to resolve the template string properly when running jest --watch. It works fine without the --watch flag.

To Reproduce

Run jest --watch with babel-jest set as the transformer on a file that contains the following:

const ImageLink = ({ linkPath, linkLabel, imageSource }: ImageLinkProps) => (
  <Link to={linkPath}>
    <img alt={`Navigation link to ${linkLabel}`} src={require(`$images/${imageSource}`)} />
    <span>{linkLabel}</span>
  </Link>
);

Expected behavior

The above code is valid and works without issue when transformed by babel-jest without the --watch flag. I expect it to work without issue with --watch set as well. However, I currently get the following error from jest (which in turn doesn't run, due to a non-existent file):

Could not locate module $images/${imageSource} mapped as:
/home/thisissami/code/s2sFrontEnd/static/images/${imageSource}.

Please check your configuration for these entries:
{
  "moduleNameMapper": {
    "/^\$images(.*)/": "/home/thisissami/code/s2sFrontEnd/static/images$1"
  },
  "resolver": null
}

This clearly means that babel-jest is not resolving the template string within the require, and is rather treating the template string as a normal string. When changing the above code to the following, babel-jest transforms without issue with the --watch mode:

const ImageLink = ({ linkPath, linkLabel, imageSource }: ImageLinkProps) => {
  const src = `$images/${imageSource}`;

  return (
    <Link to={linkPath}>
      <img alt={`Navigation link to ${linkLabel}`} src={require(src)} />
      <span>{linkLabel}</span>
    </Link>
  );
};

Run npx envinfo --preset jest

Paste the results here:

  System:
    OS: Linux 4.15 Pop!_OS 18.04 LTS
    CPU: (8) x64 Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz
  Binaries:
    Node: 10.8.0 - ~/.nvm/versions/node/v10.8.0/bin/node
    npm: 6.4.0 - ~/.nvm/versions/node/v10.8.0/bin/npm
  npmPackages:
    jest: ^23.5.0 => 23.6.0
@SimenB
Copy link
Member

SimenB commented Dec 13, 2018

Would you mind putting up a quick reproduction that does not use react but still show the error?

@otakustay
Copy link

otakustay commented Apr 10, 2019

I have created a reproduction may related to this issue: https://github.com/otakustay/jest-bug-demo

yarn
jest --watch

jest will be success while jest --watch will fail

This is also referenced in #4552

@sem4phor
Copy link

The same thing happens if using the --findRelatedTests cli option. Any updates?

@thisissami
Copy link
Author

@SimenB @thymikee any updates? There's been a reproduction for several months now.

@thisissami
Copy link
Author

Here's another reproduction using React. https://codesandbox.io/s/jest-test-wylir If you run that with jest --watch it will not work. Adding this to update that using newer ES dynamic imports, the same thing happens. it is not limited to just require.

@thisissami
Copy link
Author

@SimenB @thymikee if you guys can point me to where the relevant files would be, I'd be happy to take a look and see if I fix this bug. It's really frustrating to have to have 2 different sets of code (one for running the server, and one for testing) that we have to keep commenting out/in - depending on what our use case is.

The requirement by jest --watch to define the url in a separate variable before requiring/importing it makes it so that webpack is unable to resolve things, as it interprets an alias in the url (which we are using) as an actual destination.

@jeysal
Copy link
Contributor

jeysal commented Jul 7, 2019

Hi @thisissami, I've just taken a look at this.
@otakustay's repo seems like a different issue and it has been discussed in #4552 already.
Unfortunately, your Codesandbox contains a lot of incompatible dependencies, such as Jest 24 and Babel 6, and lots of extra code, so I'm not sure how useful it is to debug this. I took the time to make a proper minimal repro that I think describes the same issue: https://github.com/jeysal/jest-7511-repro
I haven't had the time to dive into this much deeper though. It's clearly caused by configuring a moduleNameMapper and adding an import that it applies (doesn't happen otherwise), but I'm not sure why this matters or why it doesn't crash otherwise (no idea what code decides not to detect a template string as a dependency when doing static analysis to figure out dependencies for watch/findRelatedTests).
If you want to have a go, the interesting places are probably jest-haste-map and its dependencyExtractor (where the files are statically searched for dependencies), SearchSource where the findRelatedTests operation is performed, and jest-resolve-dependencies, which is used there, and jest-resolve, which is in turn used there and considers the moduleNameMapper option.

@thisissami
Copy link
Author

Thanks for the info @jeysal. I've found a workaround in the meantime that allows our codebase to not need to change between running jest --watch and everything else. For the files in question, just removing the alias and instead having a ../../../../folder1/folder2/file does the trick. I'm accordingly not going to bother, given that there's a large number of possible locations.

I do find it a bit weird that running jest without the --watch flag works without issue though. I wonder what changes there that makes aliases problematic.

@thisissami
Copy link
Author

I think after playing around with various things, the bigger issue is the alias. i tried breaking things out into 2 normal strings being concatenated together (before trying this workaround), and the alias wouldn't work with --watch mode using that approach either.

@jeysal
Copy link
Contributor

jeysal commented Jul 8, 2019

I do find it a bit weird that running jest without the --watch flag works without issue though. I wonder what changes there that makes aliases problematic.

The static analysis, trying to figure out dependencies between files in order to determine which tests relate to SCM-changed files and need to be rerun, is probably the thing happening only in watch mode that breaks down here.

@ant1m4tt3r

This comment has been minimized.

@SimenB
Copy link
Member

SimenB commented Aug 8, 2019

You can verify the above by running jest --only-changed (or jest -o for short) which does the same thing --watch does when it comes to VCS

@JJBocanegra
Copy link

Using --watchAll works correctly.

@github-actions
Copy link

This issue 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 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants