# Configuration

## Backend Selection

Tests run against both backends by default: `'webgpu'` and `'webgl'` (WebGPURenderer with `forceWebGL: true`).

### Per-Call Selection

```ts
import { it } from "vitest";
import { gpuTest } from "vitest-browser-three";
import { float } from "three/tsl";

it("smoke", async () => {
  // Test specific backends
  await gpuTest("smoke", ({ eq }) => eq(float(2).add(3), float(5)), {
    backends: ["webgpu", "webgl"],
  });
});

it("webgpu only", async () => {
  // WebGPU only (for features like subgroups)
  await gpuTest("webgpu only", ({ eq }) => eq(float(2).add(3), float(5)), {
    backends: ["webgpu"],
  });
});
```

### Suite-Level Defaults

The library does not provide a suite-level default API. Backend selection
is per-call. If you want a suite-wide default, define a one-line wrapper
in your own test file or setup module:

```ts
import { gpuTest, gpuFuzzTest } from "vitest-browser-three";

const withBackends = (backends) => ({
  gpuTest: (name, fn, opts = {}) =>
    gpuTest(name, fn, { ...opts, backends: opts.backends ?? backends }),
  gpuFuzzTest: (name, spec) => gpuFuzzTest(name, { ...spec, backends: spec.backends ?? backends }),
});

const { gpuTest: webgpuTest } = withBackends(["webgpu"]);
```

Or a single-test wrapper if you only need `gpuTest`:

```ts
const webgpuTest = (name, fn, opts = {}) =>
  gpuTest(name, fn, { ...opts, backends: opts.backends ?? ["webgpu"] });
```

**Why no library-provided factory?** A wrapper this small is better kept
in user code where it can read from environment variables, adapt per
`describe` block, or compose with other defaults — none of which a
fixed factory can do. See `docs/DECISIONS.md` for the design rationale.

Per-call `backends` always wins over any wrapper default:

```ts
await webgpuTest("override", ({ eq }) => eq(float(1), float(1)), {
  backends: ["webgl"], // this one runs on WebGL despite the wrapper default
});
```

`DEFAULT_BACKENDS` (a frozen readonly constant, `['webgpu', 'webgl']`)
is what `gpuTest` / `gpuFuzzTest` fall back to when no `backends` option
is provided at any level.

## Environment Probing

```ts
import { it } from "vitest";
import { isBackendAvailable } from "vitest-browser-three";

it("probes available backends", async () => {
  const webgpu = await isBackendAvailable("webgpu");
  const webgl = await isBackendAvailable("webgl");

  if (!webgpu && !webgl) {
    console.warn("No GPU backend available");
  }
});
```

## Soft Skip Behavior

Unavailable backends are soft-skipped with a warning. The test only fails when no requested backend is available:

```
[vitest-browser-three] gpuTest "smoke": skipping "webgpu" backend is not available in this environment.
```

Failures are tagged with `[backend: xxx]` (appended on a new line):

```
Assertion failed: expected 5, got 3
(failed on [backend: webgpu])
```

## Renderer Cleanup

The default entry auto-disposes the shared GPU renderer via `afterAll`:

```ts
import { gpuTest } from "vitest-browser-three"; // auto-cleanup
```

If you import from the side-effect-free entry, add cleanup manually:

```ts
import { afterAll } from "vitest";
import { disposeRenderer } from "vitest-browser-three/pure";

afterAll(async () => {
  await disposeRenderer();
});
```
