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

Vite test error cannot be imported in a CommonJS module using require() #8729

Closed
sbland opened this issue Mar 31, 2024 · 3 comments
Closed

Comments

@sbland
Copy link

sbland commented Mar 31, 2024

Describe the bug

I'm trying to create a setup test files for vite in a custom react environment with some mocked modules. Unfortunately when running the tests I get an error related to Vitest cannot be imported in a CommonJS module using require()

Full error:


 FAIL  myorg/node-search.spec.tsx [ myorg/node-search.spec.tsx ]
Error: Vitest cannot be imported in a CommonJS module using require(). Please use "import" instead.

If you are using "import" in your source code, then it's possible it was bundled into require() automatically by your bundler. In that case, do not bundle CommonJS output since it will never work with Vitest, or use dynamic import() which is available in all CommonJS modules.
 ❯ Object.<anonymous> node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vitest/index.cjs:1:7
 ❯ vi myorg/envs/react-env-custom/setup/setup-tests.tsx:1:1
 ❯ myorg/envs/react-env-custom/setup/setup-tests.tsx:6:1

Steps to Reproduce

react-env-custom.bit-env.ts

  tester(): EnvHandler<Tester> {
    return VitestTester.from({
      config: require.resolve('./config/vitest.config.mjs'),
    });
  }

vitetest.config.mjs

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

import { createRequire } from 'node:module';

const require = createRequire(import.meta.url);
const setupPathName = require.resolve('../setup/setup-tests.js');

export default defineConfig({
  plugins: [react()],
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: [setupPathName],
  },
});

setup-tests.ts

import { vi } from 'vitest'
import '@testing-library/jest-dom'


vi.mock('@my-org.mockme', () => ({
  __esModule: true,
  default: () => ({
    get: (k) =>
      ({
        port: 100
      }[k]),
  }),
}));

Running a test with the above setup results in the error below:

 FAIL  cam/collect-and-map/core/node-search/node-search.spec.tsx [ cam/collect-and-map/core/node-search/node-search.spec.tsx ]
Error: Vitest cannot be imported in a CommonJS module using require(). Please use "import" instead.

If you are using "import" in your source code, then it's possible it was bundled into require() automatically by your bundler. In that case, do not bundle CommonJS output since it will never work with Vitest, or use dynamic import() which is available in all CommonJS modules.
 ❯ Object.<anonymous> node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vitest/index.cjs:1:7
 ❯ vi cam/envs/react-env-custom/setup/setup-tests.tsx:1:1
 ❯ cam/envs/react-env-custom/setup/setup-tests.tsx:6:1

Specifications

  • Bit version: 1.6.2
  • Workspace type: harmony
  • Node version: v18.19.1
  • npm / yarn version:v10.2.4
  • Platform: ubuntu

for harmony workspace

  • relevant env: custom env from @teambit/react.react-env
@itaymendel
Copy link
Contributor

this is likely a CJS<>ESM issue, as the compilation type from teambit/react is CJS.
i recommend basing your custom env on @bitdev/react.react-env instead (just add that depenency, and change you import statement). this env adds type:module and such, so target is esm.
https://bit.cloud/bitdev/react/react-env

@sbland
Copy link
Author

sbland commented Apr 4, 2024

Thanks @itaymendel but no luck. I also tried adding esm: true to the compiler. Full env file below:

/**
 * this env uses bitdev.react/react-env
 * to inspect its config @see https://bit.cloud/bitdev/react/react-env
 */
import { ReactEnv } from '@bitdev/react.react-env';
import typescript from 'typescript';
import { TypeScriptExtractor } from '@teambit/typescript';
import { SchemaExtractor } from '@teambit/schema';
import { Compiler } from '@teambit/compiler';
import { ReactPreview } from '@teambit/preview.react-preview';
import { EnvHandler } from '@teambit/envs';
import { Pipeline } from '@teambit/builder';
import { ESLint as ESLintLib } from 'eslint';
import {
  TypescriptCompiler,
  resolveTypes,
  TypescriptTask,
} from '@teambit/typescript.typescript-compiler';
import { ESLintLinter, EslintTask } from '@teambit/defender.eslint-linter';
// import { JestTester, JestTask } from '@teambit/defender.jest-tester';
import { VitestTester, VitestTask } from '@teambit/vite.vitest-tester';
import { PrettierFormatter } from '@teambit/defender.prettier-formatter';
import { Tester } from '@teambit/tester';
import { Preview } from '@teambit/preview';
import hostDependencies from './preview/host-dependencies.js';
import { webpackTransformer } from './config/webpack.config.js';

export class ReactEnvCustom extends ReactEnv {
  /**
   * name of the environment. used for friendly mentions across bit.
   */
  name = 'react-env-custom';

  /**
   * create an instance of a Bit Component Compiler.
   * Learn more: https://bit.dev/reference/compiling/set-up-compiler
   */
  compiler(): EnvHandler<Compiler> {
    return TypescriptCompiler.from({
      esm: true,
      tsconfig: this.tsconfigPath,
      types: resolveTypes(__dirname, [this.tsTypesPath]),
      typescript,
    });
  }

  /**
   * returns an instance of the default TypeScript extractor.
   * used by default for type inference for both JS and TS.
   */
  schemaExtractor(): EnvHandler<SchemaExtractor> {
    return TypeScriptExtractor.from({
      tsconfig: this.tsconfigPath,
    });
  }

  /**
   * create an instance of the Bit Tester plugin.
   * learn more: https://bit.dev/reference/testing/set-up-tester
   */
  // Vitetest not working
  tester(): EnvHandler<Tester> {
    return VitestTester.from({
      config: require.resolve('./config/vitest.config.mjs'),
    });
  }
  // tester(): EnvHandler<Tester> {
  //   return JestTester.from({
  //     config: require.resolve('./config/jest.config.js'),
  //   });
  // }

  /**
   * add a Bit Linter plugin.
   * learn more: https://bit.dev/reference/testing/set-up-tester
   */
  linter() {
    return ESLintLinter.from({
      tsconfig: this.tsconfigPath,
      eslint: ESLintLib,
      configPath: this.eslintConfigPath,
      pluginsPath: __dirname,
      extensions: this.eslintExtensions,
    });
  }

  /**
   * create a formatter instance.
   * learn more: https://bit.dev/reference/formatting/set-up-formatter
   */
  formatter() {
    return PrettierFormatter.from({
      configPath: require.resolve('./config/prettier.config.js'),
    });
  }

  /**
   * create an instance for Bit Preview.
   */
  preview(): EnvHandler<Preview> {
    return ReactPreview.from({
      // TODO: Add webpack here
      transformers: [
        webpackTransformer,
      ],
      mounter: this.previewMounter,
      hostDependencies,
    });
  }

  /**
   * Add your build pipeline.
   * learn more: https://bit.dev/docs/react-env/build-pipelines
   */
  build() {
    return Pipeline.from([
      TypescriptTask.from({
        tsconfig: this.tsconfigPath,
        types: resolveTypes(__dirname, [this.tsTypesPath]),
        typescript,
      }),
      EslintTask.from({
        eslint: ESLintLib,
        tsconfig: this.tsconfigPath,
        configPath: this.eslintConfigPath,
        pluginsPath: __dirname,
        extensions: this.eslintExtensions,
      }),
      VitestTask.from({
        config: require.resolve('./config/vitest.config.mjs'),
      }),
      // JestTask.from({
      //   config: this.jestConfigPath,
      // }),
    ]);
  }

  protected tsconfigPath = require.resolve('./config/tsconfig.json');

  protected tsTypesPath = './types';

  protected jestConfigPath = require.resolve('./config/jest.config');

  protected eslintConfigPath = require.resolve('./config/eslintrc.js');

  protected eslintExtensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs'];

  protected prettierConfigPath = require.resolve('./config/prettier.config.js');

  protected prettierExtensions = [
    '.js',
    '.jsx',
    '.ts',
    '.tsx',
    '.mjs',
    '.cjs',
    '.json',
    '.css',
    '.scss',
    '.md',
    '.mdx',
    '.html',
    '.yml',
    '.yaml',
  ];

  protected previewMounter = require.resolve('./preview/mounter');
}

export default new ReactEnvCustom();

@Jinjiang
Copy link
Member

Jinjiang commented Apr 9, 2024

@sbland sorry for the trouble. You can try to rename the setup-tests.ts into setup-tests.mjs to keep it in ESM. Then it would work. The reason behind is all the ts files in an env will be transpiled into CJS by default. So by renaming it into .mjs, you can bypass it. I've tried it locally, it worked as expected after that. Thanks.

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

No branches or pull requests

3 participants