Windows: Multiple issues with Vitest integration and Oxlint in Bit 2.0.11
Summary
1. bit test / bit build incorrectly report "no tests found" on Windows
Tests execute successfully and Vitest reports them as passing, but Bit reports that the tested components have no tests.
I traced the cause of this to @teambit/vite.vite-tester (config-utils.ts), where Windows paths generated with path.resolve() are compared using minimatch, which expects forward slashes.
2. bit test --coverage reports 0% coverage despite that Vitest executes tests successfully
Regardless of whether the istanbul or v8 provider is used, running tests through Bit always reports 0% coverage.
Running the exact same vitest.config.mjs directly with Vitest produces the correct coverage report.
This happens even in a completely fresh Bit workspace without any custom Vitest configuration.
3. teambit.defender/linter:OxlintLint fatally stops bit build
A brand new workspace fails during bit build --skip-tests because OxlintLint throws.
On a fresh project it fails with:
Failed to spawn tsgolint ... %1 is not a valid Win32 application. (OS error 193)On an existing workspace it fails with:
spawn ENAMETOOLONGBoth errors terminate the build.
Environment
- Windows 10 / Windows 11
- Bit v2.0.11 (also tested on v2.0.2, it had these problems, as well as a few others that are already fixed)
- Node.js >= v22.16 (tested on v22.16 and v25.5)
- Clean pnpm store
- Fresh installation (no custom Vitest configuration required to reproduce)
- Fresh workspace
Issue 1: bit test reports "no tests found"
Vitest executes tests successfully:
✓ projects/converters/string-converter/string-converter.spec.ts (1 test)But Bit reports:
3 components have no tests
› projects/apps/react-frontend
› projects/converters/string-converter
› projects/envs/my-react-env
no tests found (3 components, none with tests)Root cause
I traced this to @teambit/vite.vite-tester, config-utils.ts, at line 31.
Current implementation:
const resolvePatternEntry = (patternEntry: ComponentPatternsEntry) => {
const { componentDir, paths } = patternEntry;
return paths.map((p) => {
if (p.relative.startsWith('!')) {
return `!${componentDir}/${p.relative.slice(1)}`;
}
return resolve(componentDir, p.path);
});
}On Windows:
resolve(...)returns paths using backslashes.
Those paths are later matched with minimatch, which expects forward slashes.
Changing it to:
return resolve(componentDir, p.path).replace(/\\/g, '/');fixes the issue locally.
Additional observations
When investigating, I noticed two more problems in the same file.
getCoverageInclude() has the same path normalization problem
It looks like the mirror image of the issue above.
customPatterns appear to be silently discarded
Current code:
if (customPatterns && !isEmpty(customPatterns)) {
customPatterns.map((customPattern) => {
const rootDirs = opts.roots || [patternEntry.componentDir];
return resolvePattern(customPattern, rootDirs);
});
}The result of map() is never returned or used, so all custom patterns are ignored.
These are separate issues from the "no tests found" bug.
Issue 2: Coverage is always reported as 0%
Running through Bit:
bit test --coverage --verbose --debugproduces:
RUN v4.1.10 G:/Moje Pliki/Programowanie/TypeScript/Bit2
Coverage enabled with istanbul
✓ projects/converters/string-converter/string-converter.spec.ts (1 test) 5ms
✓ StringConverter (1)
✓ isNumber (1)
✓ should return true for a valid integer 3ms
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 23:00:37
Duration 1.78s (transform 279ms, setup 452ms, import 17ms, tests 5ms, environment 1.03s)
% Coverage report from istanbul
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 0 | 0 | 0 | 0 |
----------|---------|----------|---------|---------|-------------------This happens regardless of whether the coverage provider is:
istanbulv8
After fixing Issue 1 locally, the coverage problem still remains.
But, running Vitest directly with the exact same configuration:
npx vitest run --config projects/envs/my-react-env/config/vitest.config.mjs --coverage --reporter verboseproduces the expected result:
RUN v4.1.10 G:/Moje Pliki/Programowanie/TypeScript/Bit2
Coverage enabled with istanbul
✓ projects/converters/string-converter/string-converter.spec.ts > StringConverter > isNumber > should return true for a valid integer 3ms
Test Files 1 passed (1)
Tests 1 passed (1)
Start at 04:38:06
Duration 6.45s (transform 409ms, setup 652ms, import 364ms, tests 5ms, environment 4.97s)
% Coverage report from istanbul
---------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------------|---------|----------|---------|---------|-------------------
All files | 75 | 87.5 | 100 | 75 |
string-converter.ts | 75 | 87.5 | 100 | 75 | 4
---------------------|---------|----------|---------|---------|-------------------So:
- the tests execute correctly,
- the configuration is correct,
- Vitest itself generates correct coverage,
but invoking the same configuration through Bit always produces an empty coverage report.
Issue 3: OxlintLint prevents builds
Running
bit build --skip-testsin a fresh workspace fails with:
× env: projects/envs/my-react-env, task "teambit.defender/linter:OxlintLint" threw an error
oxlint returned non-JSON output:
Error running tsgolint: "Failed to spawn tsgolint from path `G:\\Moje Pliki\\Programowanie\\TypeScript\\Bit2\\node_modules\\.pnpm\\[email protected]\\node_modules\\oxlint-tsgolint\\bin\\tsgolint.js`, with error: %1 is not a valid Win32 application. (OS error 193)". (os error 193)"In an existing workspace another fatal error occurs:
× env: projects/commonlib/envs/my-react-env, task "teambit.defender/linter:OxlintLint" threw an error Command failed with ENAMETOOLONG: G:\Moje Pliki\Programowanie\TypeScript\Bit\node_modules\.pnpm\[email protected][email protected]\node_modules\oxlint\bin\oxlint C:\Users\<User>\AppData\Local\Bit\capsules\2c2020618\projects_commonlib_components_my-css-grid\index.ts C:\Users\<User>\AppData\Local\Bit\capsules\2c2020618\projects_commonlib_components_my-css-grid\my-css-grid.composition.tsx (...) --type-aware --config=G:\Moje Pliki\Programowanie\TypeScript\Bit\node_modules\.pnpm\@projects+commonlib.envs.my_5aa7f7ca1e9dd92cfb0f8436b1e31a21\node_modules\@projects\commonlib.envs.my-react-env\dist\config\oxlintrc.json --tsconfig=G:\Moje Pliki\Programowanie\TypeScript\Bit\node_modules\.pnpm\@projects+commonlib.envs.my_5aa7f7ca1e9dd92cfb0f8436b1e31a21\node_modules\@projects\commonlib.envs.my-react-env\dist\config\tsconfig.json --format=json spawn ENAMETOOLONGduring the oxlint task.
Both errors terminate the build.
Steps to reproduce
Run:
bit init --default-scope projects
bit install
bit create react-env envs/my-react-env --aspect bitdev.react/react-env
bit create react-app apps/react-frontend --env projects/envs/my-react-env
bit create module converters/string-converter --env projects/envs/my-react-envReplace the generated files with the following:
string-converter.ts
export class StringConverter {
static isNumber(str: string): boolean {
if (str === null || str === undefined || str.trim().length < 1 || str === "") {
return false;
}
const num = Number(str);
return !isNaN(num) && isFinite(num);
}
}string-converter.spec.ts
import { StringConverter } from "./string-converter.js";
describe("StringConverter", () => {
describe("isNumber", () => {
it("should return true for a valid integer", () => {
expect(StringConverter.isNumber("123")).toBe(true);
});
});
});index.ts
export { StringConverter } from "./string-converter.js";string-converter.docs.mdx
---
labels: ['StringConverter', 'module']
description: 'A StringConverter module.'
---
A StringConverter module.
```ts
StringConverter();
```Then run:
bit compile
bit envs
bit status
bit build --skip-tests
bit test --coverage --verbose --debug
npx vitest run --config projects/envs/my-react-env/config/vitest.config.mjs --coverage --reporter verboseThe full command output: reproduce - output.txt
Expected behaviour
bit testshould correctly detect and report executed tests.bit test --coverageshould produce the same coverage report as running Vitest directly with the same configuration.bit buildshould complete successfully in a newly created workspace withoutOxlintLintthrowing fatal errors.
Actual behaviour
- Bit reports tested components as having no tests.
- Coverage is always reported as 0%.
OxlintLintthrows fatal errors that stop the build.
Source: teambit/bit