jest-community / vscode-jest

The optimal flow for Jest based testing in VS Code
MIT License
2.84k stars 295 forks source link

[error] failed to retrieve test file list. TestExplorer might show incomplete test items #1005

Closed JoshuaVSherman closed 1 year ago

JoshuaVSherman commented 1 year ago

Environment

  1. vscode-jest version: [5.2.3]
  2. node -v: [18.14.0]
  3. npm -v : [9.3.1]
  4. npm ls jest or npm ls react-scripts (if you haven’t ejected): [npm]
  5. your vscode-jest settings if customized:
    • jest.jestCommandLine? [empty] (I have also tried with jest command here and it does not matter)
    • jest.autoRun? [have tried both ways here as well, no difference]
    • anything else that you think might be relevant? [this is a typescript project]
  6. Operating system: [ubuntu]

Prerequisite

Steps to Reproduce

https://github.com/WebJamApps/JaMmusic

Relevant Debug Info

I gave you this on the other issue and you didn't seem to be able to help there, you closed it as fixed, but it is not fixed, sorry

Expected Behavior

It should work as it did before I did a vscode update, in which time it ran and would run on individual tests on save and this extension is very useful (hope you all can get it fixed again soon ! )

Actual Behavior

runs a few tests then stops with an Error message (see title of this ticket)


The fastest (and the most fun) way to resolve the issue is to submit a pull-request yourself. If you are interested, feel free to check out the contribution guide, we look forward to seeing your PR...

connectdotz commented 1 year ago

Thanks for the repo, I can finally see what is happening. Let me see if I can explain:

  1. in 5.x we added the logic to auto-config jest.jestCommandLine by picking up the "test" script in package.json, if found. While in 4.6, we will just fallback to the "jest" binary in the node_modules.
  2. The test script in your package.json calls another npm script, which is perfectly fine, but the arguments we added (--listTests --json for example) to the npm run test did not get carried to the 2nd script "test:jest", therefore the run failed.

I couldn't think of a simple way for us to fix this issue without parsing users' packge.json scripts, even that probably still won't be able to address every scenario. This leads me to the conclusion that user customization is the best way to go; and it's precisely what the settings are for. It is pretty simple, and there are multiple ways you can fix it yourself:

  1. use the underlying script instead: "jest.jestCommandLine": "npm run test:jest --"
  2. or use jest directly: "jest.jestCommandLine": "./node_modules/.bin/jest"
  3. or adding "--" in your test script in package.json: "test": "npm run test:lint && npm run test:jest --"

Let me know if you still have any problem.

JoshuaVSherman commented 1 year ago

@connectdotz thank you, fixed! Where is a link to your tip jar?!

iFreilicht commented 1 year ago

For anyone else who finds this issue, I want to offer an additional solution as I couldn't use the ones recommended by @connectdotz.

To make our tests work in parallel, a collaborator removed all database cleanups in the afterAll hooks and instead added a database cleanup step after the jest invocation in package.json:

    "test": "NODE_ENV=test jest --testPathIgnorePatterns=\".*.mock.spec.ts$\" --testPathIgnorePatterns=\".*.testcase.spec.ts$\" && yarn database:reseed",

My test command was set like "jest.jestCommandLine": "yarn test", which worked fine before, but now any additional commands got passed to yarn database:reseed, not to jest.

To fix this, I made use of jests globalTeardown option. So first, in package.json:

  "jest": {
    ...
    "globalTeardown": "./scripts/jest-global-teardown.ts",

And then, in ./scripts/jest-global-teardown.ts:

import { exec } from 'child_process';
import { promisify } from 'util';
export default async () => {
  // Reseed the database after all tests have run instead of running prisma.deleteMany() in every
  // afterAll() hook to prevent tests from interfering with each other
  // Specifically, use jests globalTeardown option instead of appending `&& yarn database:reseed`
  // to the test commands to allow passing additional command line options to jest
  process.stdout.write('📇 Reseeding database... ');
  await promisify(exec)('yarn database:reseed');
  process.stdout.write('Done!\n');
};

I'm sharing this here because it took me multiple steps to arrive at a working solution. Hopefully it will be helpful for someone else, too!