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

Running tests from whole folder does not work, wrong testPathPattern option #1079

Closed
akwodkiewicz opened this issue Oct 13, 2023 · 7 comments · Fixed by #1080
Closed

Running tests from whole folder does not work, wrong testPathPattern option #1079

akwodkiewicz opened this issue Oct 13, 2023 · 7 comments · Fixed by #1080
Labels

Comments

@akwodkiewicz
Copy link
Contributor

akwodkiewicz commented Oct 13, 2023

Environment

  1. vscode-jest version: v6.0.1
  2. node -v: v18.16.0
  3. npm -v or yarn --version: 3.4.1
  4. npm ls jest or npm ls react-scripts (if you haven’t ejected):

yarn why jest

...
└─ my-backend-project@workspace:packages/backend
   └─ jest@npm:29.1.2 [bd4e4] (via npm:29.1.2 [bd4e4])
  1. your vscode-jest settings if customized:
    my.code-workspace:
...
    "jest.autoRun": "off",
    "jest.virtualFolders": [{
      "rootPath": "packages/backend",
      "name": "Backend Unit Tests", 
    }],
...
  1. Operating system: macOS 14.0 (23A344) (Sonoma)

Prerequisite

  • are you able to run jest test from the command line? yes
  • how do you run your tests from the command line? (for example: npm run test or node_modules/.bin/jest) yarn test

Steps to Reproduce

  1. Open "Testing" tab

  2. Try to "Run Test" on a "folder" item (for the purpose of troubleshooting, I'm selecting the redis folder in my project).

Screenshot 2023-10-13 at 11 34 44

Relevant Debug Info

I'm running VSCode from a .code-workspace file, this is a monorepo, but I don't have multiple roots defined (and I don't want to have them). I'm trying this new virtualFolder setup.

Might be unrelated to the issue, though. (EDIT: it probably is the issue, see the next comment)

Full path to the redis folder:

  • /Users/akwodkiewicz/Private/repo-A/packages/backend/src/redis

Relative path to the .code-workspace file

  • packages/backend/src/redis

Expected Behavior

All tests from the selected folder are run.

Actual Behavior

No tests are found.

"Test Results" tab output (added line breaks in command for readability):

> my-backend-project@0.0.1 test
> env-cmd -f .env jest \
    --testLocationInResults \
    --json \
    --useStderr \
    --outputFile /var/folders/9v/c77m1k_90wl3225q3pl3335w0000gq/T/jest_runner_my-backend-project_unit_tests_503_2.json \
    --no-coverage \
    --reporters default \
    --reporters /Users/akwodkiewicz/.vscode/extensions/orta.vscode-jest-6.0.1/out/reporter.js \
    --colors \
    --watchAll=false \
    --testPathPattern /Users/akwodkiewicz/Private/repo-A/src/redis

No tests found, exiting with code 1
Run with `--passWithNoTests` to exit with code 0
In /Users/akwodkiewicz/Private/repo-A/packages/backend/src
  7472 files checked.
  testMatch:  - 0 matches
  testPathIgnorePatterns: /node_modules/ - 7472 matches
  testRegex: \.spec\.ts$ - 1412 matches
Pattern: /Users/akwodkiewicz/Private/repo-A/src/redis - 0 matches
npm ERR! Lifecycle script `test` failed with error: 
npm ERR! Error: command failed 
npm ERR!   in workspace: my-backend-project@0.0.1 
npm ERR!   at location: /Users/akwodkiewicz/Private/repo-A/packages/backend 

It looks like the --testPathPattern should be set to redis -- then searching for this path pattern would be successful In /Users/akwodkiewicz/Private/repo-A/packages/backend/src.

However, the script is passed a faulty concatenation of the workspace absolute path (/Users/akwodkiewicz/Private/repo-A), the outer src folder (which is visible in the "Testing tab", but I did not put it on the screenshot), and redis.

EDIT: The --testPathPattern is wrong, but a better analysis of what happens is in the next comment

@akwodkiewicz
Copy link
Contributor Author

Screenshot 2023-10-13 at 11 51 55

When I'm clicking "play" on the oauth folder (location: packages/backend/src/auth/oauth), I get the following output:

> my-backend-project@.0.1 test
> env-cmd -f .env jest \
    ... \
    --testPathPattern /Users/akwodkiewicz/Private/repo-A/src/auth/oauth

No tests found, exiting with code 1
Run with `--passWithNoTests` to exit with code 0
In /Users/akwodkiewicz/Private/repo-A/packages/backend/src
  7472 files checked.
  testMatch:  - 0 matches
  testPathIgnorePatterns: /node_modules/ - 7472 matches
  testRegex: \.spec\.ts$ - 1412 matches
Pattern: /Users/akwodkiewicz/Private/repo-A/src/auth/oauth - 0 matches
npm ERR! Lifecycle script `test` failed with error: 
npm ERR! Error: command failed 
npm ERR!   in workspace: my-backend-project@0.0.1 
npm ERR!   at location: /Users/akwodkiewicz/Private/repo-A/packages/backend 

The pattern passed to the script is always the concatenation of:

  • path to the workspace: /Users/akwodkiewicz/Private/repo-A/
  • relative path to the folder, from the project directory: src/auth/oauth

It's missing the packages/backend part, which is the rootPath defined in the virtualFolders option!

@akwodkiewicz
Copy link
Contributor Author

akwodkiewicz commented Oct 13, 2023

I believe the --testPathPattern is set here:

case 'by-file-pattern': {
const regex = this.quoteFilePattern(escapeRegExp(this.request.testFileNamePattern));
args.push('--watchAll=false', '--testPathPattern', regex);

And the value for testFileNamePattern might be set here:

return {
type: 'by-file-pattern',
updateSnapshot,
testFileNamePattern: this.uri.fsPath,
};

And uri there is crafted with this static method:

export class FolderData extends TestItemDataBase {
static makeUri = (parent: vscode.TestItem, folderName: string): vscode.Uri => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return vscode.Uri.joinPath(parent.uri!, folderName);
};


When you look at the VirtualWorkspaceFolder you can see a effectiveUri property:

export class VirtualWorkspaceFolder implements vscode.WorkspaceFolder {
// the URI with the rootPath applied
private effectiveUri: vscode.Uri;
constructor(
public readonly actualWorkspaceFolder: vscode.WorkspaceFolder,
public readonly name: string,
rootPath?: string
) {
this.effectiveUri = rootPath
? vscode.Uri.file(toAbsoluteRootPath(actualWorkspaceFolder, rootPath))
: actualWorkspaceFolder.uri;
}
get index(): number {
return this.actualWorkspaceFolder.index;
}
get uri(): vscode.Uri {
return this.actualWorkspaceFolder.uri;
}
/** check if the given uri falls within the virtual folder's path */
isInWorkspaceFolder(uri: vscode.Uri): boolean {
return uri.fsPath.startsWith(this.effectiveUri.fsPath);
}
}

The comment above it sounds like it's something we need. But the effectiveUri is only used to determine if something is in the virtual workspace folder, the uri property does not use this effectiveUri.

Is it possible that the fix would look like this?

   get uri(): vscode.Uri { 
     return this.effectiveUri; 
   } 

@akwodkiewicz
Copy link
Contributor Author

akwodkiewicz commented Oct 13, 2023

Ok, I think it's something like this:

The URI of the virtual workspace folder is defined to be the same as the "actual workspace folder". There's even a unit test for this

it('should returns the same uri as the actual folder', () => {
expect(virtualFolder.uri).toEqual(workspaceFolder.uri);
});

So whenever we run the command for my repo-A/packages/backend virtual folder, we're going to use the repo-A URI to calculate some paths.

To establish the test path patterns, we need to craft the URIs with the help of FolderData.makeUri. It joins a folder name with the parent URI. So it explains why oauth is prefixed with auth and auth is prefixed with src -- it matches what I see in the GUI.

But, then there's a question of "what is the root parent element"? And I think the answer is in line 194:

private addFolder = (parent: FolderData | undefined, folderName: string): FolderData => {
const p = parent ?? this;

If there are no parents, then the root is the this, which refers to the WorkspaceRoot class.

It would then explain why

  • oauth is prefixed by the parent:
    • auth and its parent:
      • src and then, since this is the root of the virtual folder, we don't have any parents (I guess), so we're left with this:
        • /Users/akwodkiewicz/Private/repo-A/

and the packages/backend is missing from the equation.

We would need to somehow add the information about the effectiveUri to the WorkspaceRoot or use VirtualWorkspaceFolder-specific methods instead of FolderData static ones to account for the rootPath of the virtual folder.

@akwodkiewicz
Copy link
Contributor Author

I think the only way to make it work is for the VirtualWorkspaceFolder to return effectiveUri as the URI. This is even mentioned in the class comment

* Note: The class will have the same index as the actual workspace folder, but different name and uri (if it has set a different rootPath).

This makes sense, cause the "virtualness" of the folder is transparent to the context class, so it should behave as a real folder and return its real URI.

I'll try to prepare a PR tonight

@connectdotz
Copy link
Collaborator

connectdotz commented Oct 13, 2023

@akwodkiewicz, good catch and nice investigation. 👍

But let's not change the uri for the virtualWorkspaceFolder, as many vscode and other components use, and assume that attribute yields the same as the original vscode.WorkspaceFolder. I think we might be able to fix this with a much narrower change:

  1. expose effectiveUri attribute in VirtualWorkspaceFolder (readonly)
  2. change the WorkspaceRoot.createTestItem() to use the effectiveUri for virtualWorkspaceFolder:
    this.context.ext.workspace.uri,

I hope this is enough to fix the issue and look forward to the PR!

@akwodkiewicz
Copy link
Contributor Author

@connectdotz, thanks for the suggestions.

But let's not change the uri for the virtualWorkspaceFolder, as many vscode and other components use, and assume that attribute yields the same as the original vscode.WorkspaceFolder.

Do you mean the setup wizard? (maybe it's broken too 😅)

I followed your advice and prepared a PR according to your proposal: #1080

I launched the modified extension on my repo and it worked correctly!

@romanlex
Copy link

romanlex commented Jan 12, 2024

Sorry but it doesn't work without any virtual folders(
In my case "jest.rootPath": "client/src" and when I'm try to run test on folder by interface I get command

DEFAULT_LOCALE=ru jest --testLocationInResults --json --useStderr --outputFile /tmp/jest_runner_stoege_1000_2.json --no-coverage --reporters default --reporters /home/wsl/.vscode-server/extensions/orta.vscode-jest-6.1.0/out/reporter.js --colors --watchAll=false --testPathPattern /home/wsl/Development/app/core

where testPathPattern is ignore rootPath
it must be --testPathPattern /home/wsl/Development/app/${rootPath}/core

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants