npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@epicat/toon-reporter

v0.0.12

Published

A minimal Vitest reporter optimized for LLM consumption

Readme

toon-reporter

A minimal Vitest and Playwright reporter optimized for LLM consumption. Outputs test results in a compact, token-efficient format.

Installation

npm install @epicat/toon-reporter

Usage

Vitest

CLI

npx vitest run --reporter=@epicat/toon-reporter

Config

// vitest.config.ts
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    reporters: ['@epicat/toon-reporter'],
  },
})

Playwright

Config

// playwright.config.ts
import { defineConfig } from '@playwright/test'

export default defineConfig({
  reporter: [['@epicat/toon-reporter/playwright']],
})

With options

// playwright.config.ts
import { defineConfig } from '@playwright/test'

export default defineConfig({
  reporter: [
    ['@epicat/toon-reporter/playwright', {
      outputFile: 'test-results.toon'
    }]
  ],
})

Output Format

All tests passing

passing: 42

With failures (Vitest)

passing: 40
failing[2]:
  - at: src/utils.test.ts:15:12
    expected: "7"
    got: "6"
  - at: src/api.test.ts:42:8
    error: TypeError: Cannot read property 'id' of undefined

With failures (Playwright)

passing: 1
failing[1]{at,expected,got}:
  "login.spec.ts:7:42",Welcome,Hello World

With parameterized test failures (Vitest)

Uses TOON tabular format for uniform parameter arrays:

passing: 6
failing[2]:
  - at: math.test.ts:16:17
    parameters[2]{expected,got}:
      "1","2"
      "4","2"

With todo/skipped tests

Uses TOON tabular format for uniform arrays:

passing: 38
todo[1]{at,name}:
  "src/api.test.ts:15:3",implement error handling
skipped[2]{at,name}:
  "src/utils.test.ts:8:3",handles edge case

With test name filtering

When using --testNamePattern or -t, results show a (filtered) indicator:

passing: 5 (filtered)
skipped: 42

With timing enabled

When timing: true is set, shows total duration and per-test timing:

duration: 52ms
passing[3]{at,name,ms}:
  "utils.test.ts:4:3",should be fast,1
  "api.test.ts:12:3",should handle requests,50
  "db.test.ts:8:3",should be slow,1

With flaky tests (Playwright)

Tests that fail initially but pass on retry are reported as flaky:

passing: 5
flaky[1]{at,name,retries}:
  "checkout.spec.ts:12:3",should complete payment,2

With coverage (Vitest only)

Coverage is automatically included when running with --coverage. No extra configuration needed:

npx vitest run --coverage --reporter=@epicat/toon-reporter

Output includes total percentages and uncovered lines per file:

passing: 8
coverage:
  "total%":
    lines: 60.99
    stmts: 58.82
    branch: 44.34
    funcs: 57.57
  files[1]{file,uncoveredLines}:
    src/toon-reporter.ts,"12-14,19-23,32,99"
  • Total percentages: Help teams track coverage thresholds
  • Per-file uncovered lines: Give LLMs actionable info to improve coverage
  • 100% covered files are hidden by default to reduce noise

With verbose: true, all files appear with per-file percentages:

  files[2]{file,uncoveredLines,"lines%","stmts%","branch%","funcs%"}:
    src/toon-reporter.ts,"12-14,19-23,32,99",56.89,55.63,43.63,61.53
    test/test-utils.ts,"",100,100,100,100

Colors

  • Green: passing count
  • Red: failing header
  • Yellow: flaky header, skipped count, file paths
  • Gray: skipped tests (detailed list)
  • Cyan: todo tests
  • Purple: (filtered) indicator when using testNamePattern

Colors are enabled when:

  • COLOR environment variable is set, OR
  • color: true option is passed

Colors are always disabled when:

  • CI environment variable is set (hard disable)
  • Output is written to a file

Options

color

Enable/disable colored output.

// vitest.config.ts
import { defineConfig } from 'vitest/config'
import { ToonReporter } from '@epicat/toon-reporter'

export default defineConfig({
  test: {
    reporters: [new ToonReporter({ color: true })],
  },
})

Or via environment variable:

COLOR=1 npx vitest run --reporter=@epicat/toon-reporter

outputFile

Write report to a file instead of stdout.

reporters: [['@epicat/toon-reporter', { outputFile: 'test-results.txt' }]]

verbose

Include per-file coverage percentages (lines, stmts, branch, funcs) alongside uncovered lines.

reporters: [new ToonReporter({ verbose: true })]

timing

Show per-test timing information and total duration. Useful for identifying slow tests.

reporters: [new ToonReporter({ timing: true })]

Output:

duration: 1m30s52ms
passing[3]{at,name,ms}:
  "utils.test.ts:4:3",should be fast,1
  "api.test.ts:12:3",should handle requests,50
  "db.test.ts:8:3",should query slowly,90000

Line Numbers

Vitest

To get line:column information for passing tests (with timing: true), skipped, and todo tests, enable includeTaskLocation in your vitest config:

// vitest.config.ts
export default defineConfig({
  test: {
    includeTaskLocation: true,
    reporters: ['@epicat/toon-reporter'],
  },
})

Or via CLI:

npx vitest run --reporter=@epicat/toon-reporter --includeTaskLocation

Without this option, passing tests (with timing: true), skipped, and todo tests will only show the file path (not line:column). This is a Vitest limitation - test locations are only collected when this config is enabled before test collection.

Note: Failing tests always include line:column from the error stack trace, regardless of this setting.

Playwright

Playwright always includes test locations. Tests marked with test.fixme() are reported as todo, while test.skip() tests are reported as skipped.

Playwright-Specific Features

Flaky Test Detection

When retries is configured in your Playwright config, tests that fail initially but pass on retry are reported as flaky:

// playwright.config.ts
export default defineConfig({
  retries: 2,
  reporter: [['@epicat/toon-reporter/playwright']],
})

Output: flaky[1]{at,name,retries}: "test.spec.ts:5:3",should work,1

Why?

Traditional test reporters output verbose information optimized for human readability. When feeding test results to an LLM for automated fixing, this verbosity wastes tokens. This reporter outputs only what's needed:

  • Pass count
  • Failure locations with expected/got values
  • Flaky test detection with retry counts (Playwright)
  • Skipped/todo test names for context
  • Coverage totals and uncovered lines (Vitest with --coverage)

Token Efficiency

Measured on a test suite with 25 tests (16 passing, 7 failing, 1 skipped, 1 todo):

| Reporter | Tokens | vs Default | vs JSON | |----------|-------:|:----------:|:-------:| | default | 4,884 | - | -10% | | json | 5,418 | +11% | - | | toon | 212 | -96% | -96% |

TOON uses ~96% fewer tokens than standard reporters.