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

Workspace configured for Jest conflicts with IDE settings #747

Closed
evtk opened this issue Sep 4, 2018 · 19 comments · Fixed by #3766
Closed

Workspace configured for Jest conflicts with IDE settings #747

evtk opened this issue Sep 4, 2018 · 19 comments · Fixed by #3766
Assignees
Labels
blocked: retry with latest Retry with latest release or head. outdated scope: testing tools Issues related to Cypress / Jest / Playwright / Vitest support in Nx stale type: question / discussion

Comments

@evtk
Copy link

evtk commented Sep 4, 2018

Running the 'ng g jest' command will generate a jest.config.js file in the root of the project. This will override the settings for jest used by the IDE (tested so far with VS Code & WebStorm). I have currently configured jest settings in the package.json, but this of course would also be the case for any already existing config 'jest.config.js' in the root.

To fix this, I have implemented the jest builder, by using a naming convention for all jest config for NX to have a prefix of 'nx-'. In this way IDE's don't automatically pick-up the jest config generated by NX.

Can such a convention be implemented?

@skydever
Copy link
Contributor

Hi @evtk

I am using VS Code and the extension orta.vscode-jest, but I did not configure anything in package.json. I was able to get the extension running with some small changes (I wanted to be able run Jest for all projects within one Jest execution, and it seems that also fixed the IDE issue). Downside of my approach: every project is using the same setupTestFrameworkScriptFile, I do not consider project specific ones.

Here is what I did:

  • I created a global test-setup.ts in the workspace root (same content, just import 'jest-preset-angular';)
  • in angular.json I set the options.setupFile pointing to the global test-setup.ts file at each projects test configuration (next to "builder": "@nrwl/builders:jest")
  • the files entry in the tsconfig.spec.json is also pointing to the global test-setup.ts instead of the project specific one
  • Now every project is using the same setupTestFrameworkScriptFile
  • In the workspace root I created a tsconfig.spec.json to include all tests and the setupTestFrameworkScriptFile:
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "../../dist/out-tsc/global-custom-jest-integration",
    "module": "commonjs",
    "types": ["jest", "node"]
  },
  "files": ["./test-setup.ts"],
  "include": ["**/*.spec.ts", "**/*.d.ts"]
}
  • I modified the jest.config.js in the workspace root to include
    • a coverageDirectory where the coverage of the global Jest run will be written to (coverageDirectory: './coverage/custom-workspace-jest-integration')
    • the global setupTestFrameworkScriptFile: './test-setup.ts'
    • the ts-jest setup using the previously generated tsconfig.spec.json and other globals required (the @nrwl/builders:jest is adding that for a project specific run, and overriding my global one):
globals: {
    'ts-jest': {
      tsConfigFile: 'tsconfig.spec.json'
    },
    __TRANSFORM_HTML__: true
  }

Doing this I am able to run Jest globally for the whole workspace + I am able to run ng test on a single project and therefore affected:test to let nx figure out what tests need to run, and jest to execute all tests within the workspace that my IDE is using.

Maybe customizing the jest.config.js in the workspace root to dynamically create a setupTestFrameworkScriptFile that includes all project specific ones could be an option concerning my downside of the approach.

How exactly does your IDE conflict with your Jest setup? Do you also have a custom global Jest integration? I don't think that implementing a naming convention is a good idea, the IDE and the generated setup should match by default in my opinion ...

@evtk
Copy link
Author

evtk commented Sep 18, 2018

Hi @skydever,

Thanks for your very detailed post with jest setup. I have followed your setup, but I get stuck on the fact that I'm using a modulename mapper, which contains a path to a barrel. It seems like the modulenamemapper's path is always interpreted against the current working folder of the test. Meaning it will never be the same. The rootDir is constant changing (it is the working folder of the test), but if I remove the rootDir, the path cannot be found (since it is relative to the working folder).

"moduleNameMapper": { "^@namespace/(.*)$": "<rootDir>/libs/$1/src/index.ts" },

yagh :)

anyways, bottomline is that in order to use jest through your IDE and through the CLI, you have to do a lot of configuration. It just doesn't work out of the box. This is also the case for your custom setup. And in my opinion that isn't the right solution.

@skydever
Copy link
Contributor

Hi @evtk

I am new to Jest but it happened to be that I configured my nx workspace before the custom builder was done, based on #623, if you haven't seen the issue before. After I got that running the migration to the builder setup was very smooth, and not having a lib/app specific test-setup.ts is ok for me, I don't have a difference at the moment. I could kick out jest-canvas-mock (I am importing it in test-setup.ts) of some libs/apps but I am not sure if that is real a benefit, concerning performance? Side effects? If I have to use a lot of such mocks it could be hard to identify who really needs it, prior execution, if that would be a problem some time.

Maybe adding an option like --jest-global-execution to the jest schematic could help out here. This option adds a global tsconfig.spec.json (but I also like tsconfig.jest.json) file including all workspace tests and adds the globals definition to the jest.config.js + a global test-setup.ts. Separate coverage dir? At least this was working for me.

About the moduleNameMapper, I just removed it. I think resolver: '@nrwl/builders/plugins/jest/resolver' is handling that. Does this work if you, if you remove the moduleNameMapper?

And about IDE, maybe the Jest plugin should also be able to handle the lib specific setups too? What are you using? Using the nearest jest.config.js, I think that is what I would prefere. Does the Jest plugin work if you open a single lib in the ide? Did not try that ...

@thelgevold
Copy link
Contributor

@FrozenPandaz Do you have any feedback to add to this approach?

@FrozenPandaz
Copy link
Collaborator

Targeting the whole workspace seems good for a mid-sized project. You may even see performance benefits of not having to restart jest.However, you might want to make --onlyChanged a default (It's default within Facebook).. especially when your project starts to grow.

The generated jest.config.js files are reliant on having the @nrwl/builders:jest builder on top of them so that they can set some settings such as the tsConfig. (We did this to be consistent with targets such as build where you would not want the user to go and use webpack) However, this makes it difficult for IDE's to be able to utilize the configs.

With the vscode plugin, you can configure the "Path to Jest":
image. I believe you would probably want to set this in your "Workspace Settings". The only issue with it right now is that we do not have outputFile which I believe would allow it to show the results in the source file. We can create a separate issue to add that.

I do not have experience with Webstorm.

@skydever
Copy link
Contributor

thx for this 👍

I needed to set the path to jest set in my "Workspace Settings" because I am not opening vscode with the nx workspace as root folder (in such a case the extension is requiring to set the paths manually), and I also have set the path to config pointing to my modified global jest.config.js. Downside, I have to start the extension manually - the activation events do not handle that case.

I did not think about the possibility to set yarn affected:test as path to the jest binary, but what does really happen in that case? Seems like I am not able to do this if I am not opening the nx workspace as root folder in vscode :(

Testing my-lib

This command can only be run inside of a CLI project.

(node:9952) UnhandledPromiseRejectionWarning: Error: ENOENT: no such file or directory, open 'd:\some-path-where-the-nx-workspace-is-a-subfolder\dist\.nx-results'
    at Object.fs.openSync (fs.js:646:18)
    at Object.fs.writeFileSync (fs.js:1299:33)
    at writeToFile (d:\some-path-where-the-nx-workspace-is-a-subfolder\other-directory\my-nx-workspace\node_modules\@nrwl\schematics\src\utils\fileutils.js:7:8)
    at Object.writeJsonFile (d:\some-path-where-the-nx-workspace-is-a-subfolder\other-directory\my-nx-workspace\\node_modules\@nrwl\schematics\src\utils\fileutils.js:61:5)
    at WorkspaceResults.saveResults (d:\some-path-where-the-nx-workspace-is-a-subfolder\other-directory\my-nx-workspace\node_modules\@nrwl\schematics\src\command-line\workspace-results.js:64:25)
    at d:\some-path-where-the-nx-workspace-is-a-subfolder\other-directory\my-nx-workspace\node_modules\@nrwl\schematics\src\command-line\affected.js:274:38
    at step (d:\some-path-where-the-nx-workspace-is-a-subfolder\other-directory\my-nx-workspace\node_modules\@nrwl\schematics\src\command-line\affected.js:40:23)
    at Object.next (d:\some-path-where-the-nx-workspace-is-a-subfolder\other-directory\my-nx-workspace\node_modules\@nrwl\schematics\src\command-line\affected.js:21:53)
    at d:\some-path-where-the-nx-workspace-is-a-subfolder\other-directory\my-nx-workspace\node_modules\@nrwl\schematics\src\command-line\affected.js:15:71
    at new Promise (<anonymous>)

(node:9952) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:9952) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

@evtk
Copy link
Author

evtk commented Sep 23, 2018

Hi @skydever I tried to run the tests using the resolver instead of the modulename mapper. But that didn't work. I guess due to the fact @FrozenPandaz has addressed: the jest.config.js is relying on the builder. Also: configuring workspace settings to point to the affected:test command also feels a bit uncomfortable. We should not have to set these kind of options, to have the IDE to succesfully run jest. For me the scenario in which I seperate jest-config for IDE from jest-config for NX, still works best.

@skydever
Copy link
Contributor

Hi @evtk

Are you sure you added this to the global jest.config.js (pointing to a global tsconfig.spec.json)?:

globals: {
    'ts-jest': {
      tsConfigFile: 'tsconfig.spec.json'
    },
    __TRANSFORM_HTML__: true
  }

... the solution should basically work, with just little adoptions to the original jest setup without relying on the builder (most of my changes where because of the global test-setup.ts). Maybe you missed something else, but anyway - I think that the need to have multiple jest-configs is not ideal, but yes, that should always work ...

@skydever
Copy link
Contributor

@FrozenPandaz about the size of a project that has a global jest solution - I totally agree. what my current solution does concerning ide is executing all tests initially, then after a change only affected ones will be executed. this will get much slower over time, fast. I dont know how the jest cache is working in detail, maybe there is something I can turn on additionally? I am not sure what --onlyChanged really does? what is the base for the detection? I will give that a try. commiting the cache files? to start with affected what your solution would do.

@evtk
Copy link
Author

evtk commented Dec 8, 2018

it has been a while, but I have taken the effort again to stay as close as possible to the out of the box jest configuration from NX. I finally managed it, thanks to the suggestions made by @skydever.

On top of the default NX jest configuration (ng g jest + create apps/libs with --unit-test-runner jest), I have added in the root the test-setup.ts file and tsconfig.spec.json file as suggested here:

#747 (comment)

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "../../dist/out-tsc/global-custom-jest-integration",
    "module": "commonjs",
    "types": ["jest", "node"]
  },
  "files": ["./test-setup.ts"],
  "include": ["**/*.spec.ts", "**/*.d.ts"]
}

and I have adjusted the default jest.config.ts file by adding this part:

  setupTestFrameworkScriptFile: "./test-setup.ts",
  globals: {
    'ts-jest': {
      tsConfigFile: 'tsconfig.spec.json'
    },
    __TRANSFORM_HTML__: true
  }

this scenario works for me. I can now run all tests with affected:test command and by running them manually using the vs code jest plugin by Orta. I do not have any issues anymore with the module mapping. I have no clue why, but hey it works :)

For anyone, wondering, this is how my vs code launch settings:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Jest All",
      "program": "${workspaceRoot}/node_modules/.bin/jest",
      "args": [
        "--runInBand",
      ],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "windows": {
        "program": "${workspaceRoot}/node_modules/jest/bin/jest",
      }
    },
    {
      "type": "node",
      "request": "launch",
      "name": "Jest Current File",
      "program": "${workspaceFolder}/node_modules/.bin/jest",
      "args": [
        "${relativeFile}",
        "--runInBand",
      ],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen",
      "windows": {
        "program": "${workspaceFolder}/node_modules/jest/bin/jest",
      }
    }
  ]
}

@lonix1
Copy link

lonix1 commented Mar 20, 2019

I've followed @evtk's advice, and my error disappeared but was replaced by other errors. This is for a standard setup, just by following the docs.

Given that many (/most /majority ?) of node/angular devs are using vscode, surely this problem should be addressed, or at the very least, the docs should explain a workaround. As they currently stand, the official docs and cli generators don't work for setting up a project and using it with vscode. My issue shows that.

@vsavkin vsavkin added the jest label Apr 15, 2019
@vsavkin vsavkin added blocked: retry with latest Retry with latest release or head. scope: testing tools Issues related to Cypress / Jest / Playwright / Vitest support in Nx and removed scope: jest labels Dec 4, 2019
@vsavkin
Copy link
Member

vsavkin commented Dec 4, 2019

Folks. Is the issue still present when using the latest version of Nx?

@ronnyek
Copy link

ronnyek commented Mar 13, 2020

I believe this is the same thing that's experienced with webstorm, and if that is infact the case.... yes the problem still exists. I just created a new workspace with 9.x, and getting loads of errors with not being able to find zone.js, after fiddling with other settings, I've gotten it to the point where it gives an error about not being able to load html for the component

@gavindoughtie
Copy link

gavindoughtie commented Mar 15, 2020

In VSCode I see the "problem"
Error: Failed: "Zone is needed for the async() test helper but could not be found. Please make sure that your environment includes zone.js/dist/zone.js"

nx run myproject:test works just fine. This is just in a default Angular app workspace created on 3/14/2020 with the latest nx, Angular and TypeScript.

@github-actions github-actions bot added the stale label May 29, 2020
@nrwl nrwl deleted a comment from github-actions bot May 29, 2020
@FrozenPandaz
Copy link
Collaborator

Hi, sorry about this.

This was mislabeled as stale. We are testing ways to mark not reproducible issues as stale so that we can focus on actionable items but our initial experiment was too broad and unintentionally labeled this issue as stale.

@Cammisuli
Copy link
Member

Cammisuli commented Jul 13, 2020

Hey folks, we recently released 10.0.0-beta.2 which contains a migration for Jest configs (basically puts all configurations in the jest.config.js, and leaves the cli options for the builder to pass along). Because of this, we can now run Jest directly in the terminal (i.e jest -c app/my-app/jest.config.js).

Now, from what I saw from some VSCode extensions is that they don't play nicely with a monorepo style environment. They essentially just look at the root jest.config.js and don't know about the project specific files.

So I'm asking folks here, how do you expect this to work?

Personally, I'd rather have an extension that just "works". Without having to do workspaces.

@github-actions
Copy link

This issue has been automatically marked as stale because it hasn't had any recent activity. It will be closed in 14 days if no further activity occurs.
If we missed this issue please reply to keep it active.
Thanks for being a part of the Nx community! 🙏

@evtk
Copy link
Author

evtk commented Oct 5, 2020

@FrozenPandaz wow, many thanks for this latest fix for jest workspace. This seems to fix all my jest related issues! Awesome works!

@github-actions
Copy link

This issue has been closed for more than 30 days. If this issue is still occuring, please open a new issue with more recent context.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
blocked: retry with latest Retry with latest release or head. outdated scope: testing tools Issues related to Cypress / Jest / Playwright / Vitest support in Nx stale type: question / discussion
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants