---
url: https://huldoser.github.io/test-inventory/frameworks/vitest-examples.md
description: >-
  Scan React, Vue, browser mode, in-source tests and monorepos with
  test-inventory.
---

# Vitest examples

These examples use Vitest throughout. Start with the [Vitest guide](/frameworks/vitest) for installation,
your first scan and framework-specific limits. Each example shows a project's file layout; adjust its globs to
your own suite. Scanning reads the source without running tests or starting a browser.

## React with Vitest and Testing Library {#react-with-testing-library}

`trading-dashboard` keeps its tests next to its React components, in `*.test.tsx` files. JSX is read like the rest
of the code:

```tsx excerpt
// src/components/OrderTicket.test.tsx
// TODO(TRD-731): the date picker for good-till-date orders is being rebuilt
it.skip('submits a good-till-date order', async () => {
  const user = userEvent.setup();
  render(<OrderTicket symbol="AAPL" lastPrice={187.5} buyingPower={25_000} onSubmit={vi.fn()} />);
  await user.click(screen.getByRole('button', { name: 'Good till date' }));
});

it.todo('shows the estimated commission');
```

```sh
npx test-inventory "src/**/*.test.tsx" --framework vitest --output inventory.json
```

```json
{
  "fullName": "OrderTicket > submits a good-till-date order",
  "relativeFilePath": "src/components/OrderTicket.test.tsx",
  "state": "skip",
  "comments": ["TODO(TRD-731): the date picker for good-till-date orders is being rebuilt"]
}
```

```json
{
  "fullName": "OrderTicket > shows the estimated commission",
  "state": "todo",
  "bodyHash": null
}
```

## Vue with Vitest and Vue Test Utils {#vue-with-vue-test-utils}

`watchlist-vue` turns on Vitest's globals, so its specs use `describe` and `it` without importing them:

```ts excerpt
// tests/unit/Watchlist.spec.ts
import { mount } from '@vue/test-utils';
import Watchlist from '../../src/components/Watchlist.vue';
// ...
describe('when the feed is delayed', () => {
  it('shows how many minutes the quotes are delayed', () => {
    const wrapper = mount(Watchlist, { props: { quotes, delayedMinutes: 15 } });
    expect(wrapper.get('[data-test="delay-banner"]').text()).toBe('Quotes are delayed by 15 minutes');
  });

  it.todo('greys out quotes older than the delay');
});
```

```sh
npx test-inventory "tests/unit/**/*.spec.ts" --framework vitest --output inventory.json
```

A name that a file uses but never imports or declares is read as a Vitest global. The scan then looks for
`test.globals: true` in the config the file uses, the outermost one in its folder or a folder above that runs it, or
for
`vitest/globals` in a tsconfig in those folders, and warns with `globals-not-enabled` when there is neither. Here
`vitest.config.ts` turns them on:

```json
{
  "fullName": "Watchlist > when the feed is delayed > greys out quotes older than the delay",
  "suitePath": ["Watchlist", "when the feed is delayed"],
  "state": "todo"
}
```

## Vitest browser mode

`chart-browser` draws candlestick charts on a canvas and tests them in Chromium and WebKit with Vitest's browser
mode. One test is skipped in WebKit:

```ts excerpt
// src/candlestick-chart.test.ts
  // WebKit returns an empty blob for canvases larger than the device pixel ratio allows in headless mode.
  test.skipIf(server.browser === 'webkit')('exports the chart as a PNG', async () => {
```

```sh
npx test-inventory "src/**/*.test.ts" --framework vitest --output inventory.json
```

```json
{
  "fullName": "CandlestickChart > exports the chart as a PNG",
  "state": "skip",
  "isConditional": true,
  "condition": "server.browser === 'webkit'",
  "stateSource": "test"
}
```

The scan reads browser instances from the config and lists their names in each test's `projects`. Each declaration
still has one record, even when the runner executes it in two browsers. This test's record includes:

```json
{ "projects": ["chromium", "webkit"] }
```

## In-source and type tests

`strategy-engine` keeps some tests next to the code they test, inside `if (import.meta.vitest)`:

```ts excerpt
// src/pnl/format.ts
if (import.meta.vitest) {
  const { describe, it, expect } = import.meta.vitest;

  describe('formatPnl', () => {
    it('adds a plus sign to gains', () => {
      expect(formatPnl(1234.5)).toBe('+$1,234.50');
    });
```

It also has type tests in `*.test-d.ts` files:

```ts excerpt
// tests/orders/order.test-d.ts
describe('Order', () => {
  test('narrows to a limit order by its type', () => {
    const order = { symbol: 'AAPL', side: 'buy', type: 'limit', quantity: 10, limitPrice: 187.5 } as Order;
    if (order.type === 'limit') expectTypeOf(order).toEqualTypeOf<LimitOrder>();
  });
```

Scan the source files and the type test files along with the tests:

```sh
npx test-inventory "tests/**/*.{test,test-d}.ts" "src/**/*.ts" --framework vitest --output inventory.json
```

The `import.meta.vitest` check is how in-source tests are written, so it does not count as a condition:

```json
{
  "fullName": "formatPnl > adds a plus sign to gains",
  "relativeFilePath": "src/pnl/format.ts",
  "lineStart": 16,
  "state": "active",
  "isInCondition": false
}
```

```json
{
  "fullName": "Order > narrows to a limit order by its type",
  "relativeFilePath": "tests/orders/order.test-d.ts",
  "isTypeTest": true
}
```

## A Vitest monorepo {#a-monorepo}

`trading-monorepo` has three packages, each with its own Vitest config, and a root config that lists them as
projects. Scan them all from the root:

```sh
npx test-inventory "packages/*/src/**/*.test.ts" --framework vitest --output inventory.json
```

Paths are relative to the root, so each record names its package:

```json
{
  "fullName": "QuoteCache > returns the mid price of a fresh quote",
  "relativeFilePath": "packages/market-data/src/quote-cache.test.ts"
}
```

Only `market-data` turns on globals, in `packages/market-data/vitest.config.ts`. The scan finds that config from the
package's test files, so it gives no `globals-not-enabled` warning:

```json
{
  "fileCount": 3,
  "suiteCount": 3,
  "testCount": 8,
  "activeCount": 7,
  "todoCount": 1,
  "diagnosticCount": 0
}
```

To scan one package, pass it as the root: `--root packages/risk`. The framework version is read from
`node_modules` in the root or a folder above it, so a package of a monorepo gets the version installed at the top.

## Next

* [Vitest configuration and limits](/frameworks/vitest#configuration-and-limits).
* [Query recipes](/guide/recipes): filter by state, tags and other fields.
* [All framework guides](/frameworks/): scan another runner in the same project.
