vscode: Not working properly in monorepo

Describe the bug Not working properly in monorepo projects. By not working propertyly means vite could not resolve path alias becasue vitest was executed in the wrong user dir which is the root dir (which should be the package/xxx dir where vite.config exists ).

To Reproduce Run test in monorepo with resolve.alias defined in vite.config of sub package.

Expected behavior Working properly in monorepo.

Screenshots image image

Environment

(Paste info.txt content generated by the example project)

  • OS: macOS 12.0
  • VSCode version: 1.74.2
  • Vitest version: 0.26.0
  • Vitest plugin version: 0.2.34

Additional context

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 19
  • Comments: 25 (2 by maintainers)

Most upvoted comments

In nx mono-repository I was able to get this working finally using the vitest.workspace.ts method, and nothing more then the default command line options:

Notes:

  1. Use the project workspace settings to limit tests in the vitest ui. Jest tests should be excluded, or by exclusive include.
  2. Use vitest.workspace.ts to isolate vitest enabled packages using the config file glob, seems to be needed for vitest to work at the command line.
  3. Don’t try to run vitest --run in mode via project settings, rather leave it in watch as the vitest plugin needs this to report success/failure cases.
  4. I have come to avoid using the import { configDefaults } from 'vitest/config' package object values. I prefer a global config I can override in specific packages (e.g. vitest.shared.ts defines majority of test configurations)
  5. Remove test definition from vite.config.ts
  6. Don’t forget to absorb your, hopefully, already working vite.config.ts that should define viteTsConfigPaths({ root: '../../../' }) plugin
  7. Some errors that happen before the test starts can cause the result not found problem. Remember to check the vscode > outputs > vitest log. The last issue I had like this was a missing or broken alias path.
// <root>/vitest.workspace.ts
import { defineWorkspace } from 'vitest/config'

export default defineWorkspace([
  'packages/**/vitest.config.{e2e,unit}.ts',
  'packages/**/vitest.config.ts'
])
// <root>/vitest.shared.ts

import { UserConfig } from 'vitest'
import { defaultExclude } from 'vitest/config'

const config: UserConfig = {
  globals: true,
  environment: 'node',
  cache: {
    dir: '../../../node_modules/.vitest'
  },
  include: ['test/**/*.test.ts'],
  exclude: defaultExclude
}

export default config
// <root>/packages/features/some-vue-feature/vitest.config.ts

import configShared from '../../../vitest.shared'
import { defineConfig, mergeConfig } from 'vitest/config'

import viteConfig from './vite.config'
import path from 'path'
import { UserConfig } from 'vitest'

const config: UserConfig = {
  ...configShared,
  environment: 'jsdom',
  setupFiles: ['test/unit/test-setup.ts'],
  alias: {
    '@/store': path.resolve(__dirname, 'test/unit/__mocks__/store.ts'),
    '@ezwebproductions/lib-core': path.resolve(__dirname, '../../lib/core/src/index.ts')
  }
}

export default mergeConfig(
  viteConfig({ mode: 'test', command: 'build' }),
  defineConfig({
    test: config
  })
)
// <root>/packages/lib/core/vitest.config.ts

import { mergeConfig, defineConfig } from 'vitest/config'
import configShared from '../../../vitest.shared'
import viteConfig from './vite.config'

export default mergeConfig(
  viteConfig({ command: 'build', mode: 'test' }),
  defineConfig({ test: configShared })
)
// project.code-workspace
{
    "vitest.enable": true,
    "vitest.commandLine": "npx vitest",
    "vitest.exclude": [
      "**/node_modules/**",
      "**/dist/**",
      "**/cypress/**",
      "**/.{idea,git,cache,output,temp}/**",
      "packages/commonjs-only-systems/**/*.test.ts"
    ],
    "vitest.include": [
      "packages/limit/your/use/case/for/ui/tests/here/**/*.test.ts",
      "packages/features/**/*.test.ts",
      "packages/lib/idb/**/*.test.ts",
      "packages/lib/core/**/*.test.ts"
    ]
}

I got it to work using the vs code workspace workaround. You can define your workspace using a file in the root with the name yourmainfolder.code-workspace and in that folder you can add a custom vitest.commandLine to each folder:

{
  "folders": [
    {
      "path": "apps/webapp",
      "vitest.commandLine": "yarn vitest --root apps/webapp"
    },
    {
      "path": "packages/integrations",
      "vitest.commandLine": "yarn vitest --root packages/integrations"
    }
  ]
}

This works for me, using Vitest Workspace:

import { defineWorkspace } from "vitest/config";

export default defineWorkspace(["packages/*", "apps/*"]);

And nothing else.

Plus, I install vitest only in monorepo root.

This has now been properly fixed by merging #231 and #241!

Enjoy. Monorepo support should be a lot easier now, and a new NX example has been added as well. I think we can close this.

I have a few repositories for experimenting with Vitest in a monorepo setup:

https://github.com/koistya/vitest-workspaces — bare minimum Vitest config https://github.com/kriasoft/react-starter-kit — front-end monorepo https://github.com/kriasoft/relay-starter-kit — full-stack monorepo

├── app/vite.config.ts — React front-end (app) ├── edge/vite.config.ts — Cloudflare Workers (edge) ├── vitest.config.ts — Root-level Vite config └── vitest.workspaces.ts — Vitest workspaces

  • Can run tests for all workspaces (yarn test)
  • Can run tests per workspace (yarn workspace edge test)
  • Can run and debug tests using VSCode extension for Vitest

VS Code’s multi-root workspace may work for some but for many of our shared/mono repo set ups, we have one VS Code root, one .vscode/* one .git/* etc.

Rather than a multi-root issue this seems more of cwd concern.

A workaround is to edit the vitest command to include an explicit root. For me, adding the following to the workspace meant that at least one of the packages in the monorepo could show interactive test results correctly.

    "vitest.commandLine": "npx vitest --root packages/packageName/test"

In terms of the vitest-dev extension, if running from the proper root can’t be configured as default behaviour, perhaps the basedir of the file being run could be passed as a variable, meaning users could inline this logic to the vitest.commandLine as required.

This would lead to something like the following, which would mean more than one package in a monorepo could have passing tests at one time…

    "vitest.commandLine": "npx vitest --root ${baseDir}"

@steven87vt this was massively helpful. By far one of the most helpful comments I’ve seen on GitHub. Thanks a million for this!

This workaround works for subfolders

"vitest.commandLine": "npx vitest --root packages/packageName"

Check logs in vitest in output it more informative

Only problem i am facing now it skips env variables

Just messing around but here’s a start: "vitest.commandLine": "pnpm --if-present -r test --" pnpm has some create filtering options to employ too.

Worse, however, and really must be fixed, is the poor behaviour when the vitest process fails (owing to a poorly selected working directory).

The UI simply swallows errors and sits there indefinitely with spinners rather than finalising the task with an error case.

image

Behind the scenes in the Output => Vitest terminal you can see the failures which are not properly handled by vitest-dev such as the following, because it’s not loading the tsconfig.json from the parent directory and vitest.conf.ts that brings in the correct vitest globals…

 FAIL  packages/public-api/test/index.test.ts [ packages/public-api/test/index.test.ts ]
ReferenceError: describe is not defined

...

Test Files  1 failed (1)
      Tests  no tests
   Start at  12:30:15
   Duration  11.64s (transform 3.88s, setup 0ms, collect 0ms, tests 0ms)
 FAIL  Tests failed. Watching for file changes...
       press h to show help, press q to quit

Also this meaningful error content is completely missing from the inline-notified error if you configure the extension to create test error popups.

image

Hi! I’ve had the same issue and I fixed it by creating a VSCode Workspace file. Once you have one the extension seems to pick up it needs to use the workspace root your test is in 👍

You mean using Multi-root workspaces? Can you show me an example?

The project I’ve used that in is closed source (it’s at my workplace), but it’s literally just creating the file like indicated in the doc and setting one of the root path to be the folder where Vitest is installed in your repo 😉

Hi! I’ve had the same issue and I fixed it by creating a VSCode Workspace file. Once you have one the extension seems to pick up it needs to use the workspace root your test is in 👍

You mean using Multi-root workspaces? Can you show me an example?