remix-run / remix

Build Better Websites. Create modern, resilient user experiences with web fundamentals.
https://remix.run
MIT License
29.79k stars 2.51k forks source link

"Error: Remix Vite plugin can't detect preamble. Something is wrong." when running component tests with Vitest #8982

Open amanape opened 7 months ago

amanape commented 7 months ago

Reproduction

Go to https://stackblitz.com/edit/remix-run-remix-b7fgeb?file=__tests__%2Fexample.spec.tsx and run npx vitest to see the error.

Regular unit tests run fine, problem appeared when integrating component testing with @testing-library/react (which in turn required me to install happy-dom or jsdom for the testing environment).

Defining the components inside the test do not cause an error.

I was able to trace the issue to the vite.config.ts file, where including any configurations related to vitest will cause it to fail. Moving the vitest configurations to vitest.config.ts and merging the two configuration files as advised by the official documentation also causes the same error.

Temporary Solution

The only (temporary) solution I found was to separate vitest.config.ts and vite.config.ts, then everything works as expected. But that is not a good solution as according to the official documentation, overrides the vite file.

System Info

System:
    OS: macOS 14.2.1
    CPU: (8) arm64 Apple M1
    Memory: 116.03 MB / 8.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.11.0 - /usr/local/bin/node
    Yarn: 1.22.21 - ~/.yarn/bin/yarn
    npm: 10.3.0 - /opt/homebrew/bin/npm
    pnpm: 8.15.1 - /opt/homebrew/bin/pnpm
    bun: 1.0.29 - ~/.bun/bin/bun
    Watchman: 2024.01.22.00 - /opt/homebrew/bin/watchman
  Browsers:
    Brave Browser: 120.1.61.109
    Safari: 17.2.1
  npmPackages:
    @remix-run/dev: ^2.8.0 => 2.8.0 
    @remix-run/node: ^2.8.0 => 2.8.0 
    @remix-run/react: ^2.8.0 => 2.8.0 
    @remix-run/serve: ^2.8.0 => 2.8.0 
    @remix-run/testing: ^2.8.0 => 2.8.0 
    vite: ^5.1.0 => 5.1.5

Used Package Manager

npm

Expected Behavior

Tests should work as expecting without throwing

Actual Behavior

Test fail because of reasons unrelated to tests

martialanouman commented 7 months ago

It ran into the same error too while trying to run react component tests

CharlesErrington commented 7 months ago

I am also having this exact error.

martialanouman commented 7 months ago

Any update on this ?

amanape commented 7 months ago

@martialanouman

The only (temporary) solution I found was to separate vitest.config.ts and vite.config.ts, then everything works as expected. But that is not a good solution as according to the official documentation, overrides the vite file.

martialanouman commented 7 months ago

Thanks @amanape

I saw that and use it for now, but that doesn't feel clean

pcattori commented 6 months ago

Currently we recommend that the remix plugin is omitted when running with Vitest. There's a bit of work to do on our end to figure out how best to integrate with tools like Vitest and Storybook so that this sort of workaround isn't required.

yegorkay commented 5 months ago

If I did the conditional logic of process.env.VITEST && remix() I would get a new error in some of my tests:

ReferenceError: React is not defined

If you were on a Vite React SPA previously, I'm finding that you would need to keep your @vitejs/plugin-react around just for vitest:

import reactVitest from '@vitejs/plugin-react'
import { vitePlugin as remix } from '@remix-run/dev';
import { defineConfig, loadEnv } from "vite";

export default defineConfig({
  plugins: [process.env.VITEST ? reactVitest() : remix()],
  // rest of the config
});
acelaya commented 5 months ago

Currently we recommend that the remix plugin is omitted when running with Vitest. There's a bit of work to do on our end to figure out how best to integrate with tools like Vitest and Storybook so that this sort of workaround isn't required.

This generally works well, but I'm facing some issues when trying to test remix routes using @remix-run/testing. Basically, no matter what I pass, when rendering the RemixStub, it always results in a 404 error page.

Could that be a side effect of not loading the remix vite plugin while running tests with vite?

R0BB3RT commented 4 months ago

Currently we recommend that the remix plugin is omitted when running with Vitest. There's a bit of work to do on our end to figure out how best to integrate with tools like Vitest and Storybook so that this sort of workaround isn't required.

This generally works well, but I'm facing some issues when trying to test remix routes using @remix-run/testing. Basically, no matter what I pass, when rendering the RemixStub, it always results in a 404 error page.

Could that be a side effect of not loading the remix vite plugin while running tests with vite?

Currently facing the same issue. The "Remix Vite plugin can't detect preamble. Something is wrong." was solved. However now my tests using createRemixStub always render 404 error page which makes them fail.

Any solution?

brianbancroft commented 2 months ago

I am running into this exact error with a fresh remix app which attempts to use vitest with jsdom. I have another project which uses React Router which I want to port over to remix. While the app works, the tests cannot due to this issue and I am blocked.

Reproduction

https://github.com/brianbancroft/remix-cant-use-vitest

christophersesugh commented 1 month ago

This will fix the issue

import { vitePlugin as remix } from "@remix-run/dev";
import { installGlobals } from "@remix-run/node";
import tsconfigPaths from "vite-tsconfig-paths";
import { defineConfig } from "vite";

installGlobals();

const MODE = process.env.NODE_ENV;

export default defineConfig({
  build: {
    cssMinify: MODE === "production",
    rollupOptions: {
      external: [/node:.*/, "stream", "crypto", "fsevents"],
    },
  },
  server: {
    watch: {
      ignored: ["**/playwright-report/**"],
    },
  },
  plugins: [
    process.env.NODE_ENV === "test"
      ? null
      : remix({
          ignoredRouteFiles: ["**/*.css"],
        }),
    tsconfigPaths(),
  ],
  test: {
    include: ["**/__tests__/**.{js,jsx,ts,tsx}"],
    environment: "jsdom",
    setupFiles: ["./tests/setup/setup-tests-env.ts"],
    restoreMocks: true,
    coverage: {
      exclude: ["**/__tests__/**"],
      include: ["app/**/*.{ts,tsx}"],
      all: true,
    },
    alias: {
      "~": "/app",
    },
  },
});

This is a typical config file

 plugins: [
    process.env.NODE_ENV === "test"
      ? null
      : remix({
          ignoredRouteFiles: ["**/*.css"],
        }),
    tsconfigPaths(),
  ],