kobalte icon indicating copy to clipboard operation
kobalte copied to clipboard

Kobalte + SolidJS + Vitest: "Client-only API called on the server side" error in minimal jsdom test

Open adlaika opened this issue 7 months ago • 1 comments

🐛 Bug: Kobalte + SolidJS + Vitest: "Client-only API called on the server side" in minimal test

Summary

When running a minimal test for a Kobalte component (e.g., Combobox) in a SolidJS project using Vitest with jsdom, the test fails with:

Error: Client-only API called on the server side. Run client-only code in onMount, or conditionally run client-only component with <Show>.

This occurs with the latest versions of all dependencies, and after trying all known workarounds.


Minimal Reproduction

package.json

{
  "name": "solid-vitest-demo",
  "type": "module",
  "scripts": {},
  "dependencies": {
    "@kobalte/core": "^0.13.10",
    "solid-js": "^1.9.7"
  },
  "devDependencies": {
    "@solidjs/testing-library": "^0.8.10",
    "@testing-library/jest-dom": "^6.6.3",
    "jsdom": "^26.1.0",
    "vite": "^6.3.5",
    "vitest": "^3.2.1"
  }
}

vitest.config.ts

import { defineConfig } from "vitest/config";

export default defineConfig({
  test: {
    environment: "jsdom",
    setupFiles: "./setupVitest.ts",
    globals: true,
    deps: {
      inline: [/solid-js/, /@kobalte/],
    },
  },
});

setupVitest.ts

import '@testing-library/jest-dom';

src/App.test.tsx

import { render, screen } from "@solidjs/testing-library";
import { describe, it, expect } from "vitest";
import { Combobox } from "@kobalte/core/combobox";

const OPTIONS = [
  { value: "one", label: "One" },
  { value: "two", label: "Two" },
];

describe("Kobalte Combobox", () => {
  it("renders a combobox and shows options", () => {
    render(() => (
      <Combobox options={OPTIONS} optionValue="value" optionLabel="label" />
    ));
    const trigger = screen.getByRole("button");
    trigger.click();
    expect(screen.getByText("One")).toBeInTheDocument();
    expect(screen.getByText("Two")).toBeInTheDocument();
  });
});

What I’ve Tried

  • Downgrading and upgrading all relevant dependencies (solid-js, @kobalte/core, vite, vitest).
  • Switching between jsdom and happy-dom as the test environment.
  • Clearing all caches and reinstalling dependencies.
  • All known workarounds from the SolidJS and Kobalte communities.

Expected Behavior

  • The test should run in a simulated browser environment (jsdom) and render the Kobalte component without error.

Actual Behavior

  • The test fails with:
    Error: Client-only API called on the server side. Run client-only code in onMount, or conditionally run client-only component with <Show>.
    

Steps to Reproduce

  1. Create a new SolidJS project.
  2. Install the dependencies above.
  3. Add the config and test files as shown.
  4. Run pnpm exec vitest run.

Environment

  • solid-js: 1.9.7
  • @kobalte/core: 0.13.10
  • vite: 6.3.5
  • vitest: 3.2.1
  • OS: MacOS 14.6.1 (Sonoma)

adlaika avatar Jun 03 '25 17:06 adlaika

This might be an issue related to the semantics of jsdom/vitest creating what is considered an SSR environment and then running the code. Need clarification from anyone who knows these tools better. Thank you!

shayanhabibi avatar Oct 08 '25 01:10 shayanhabibi