πŸš€ Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more β†’
Socket
DemoInstallSign in
Socket

generate-jsdoc-example-tests

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

generate-jsdoc-example-tests

Generate test files from your JSDoc @example comments. See configuration details in the [vitest](#vitest) cookbook and adapt it to your favorite test runner 😊.

0.1.2
latest
Source
npm
Version published
Maintainers
1
Created
Source

generate-jsdoc-example-tests

Generate test files from your JSDoc @example comments. See configuration details in the vitest cookbook and adapt it to your favorite test runner 😊.

It offers you the certainty that your JSDoc @example are valid.

Why – TL;DR

Full announcement here.

I love documenting my functions using JSDoc examples – imo example are the best doc one can have! – but I was tired of my doc getting obsolete. And tests don't provide in-IDE doc, so I figured: why not reconcile the 2 ?
Write JSDoc examples, and generate tests from them…

  • To make sure examples never go obsolete 😍.
  • … And to test my stuff like I would anyway, you sillies πŸ€“

So here comes… generate-jsdoc-example-tests πŸŽ‰.

Prior art
  • tsdoc-testify – see Thanks. Very old and unmaintained project, an excellent base to build this one 😁.
  • jsdoc-spec – both an example parser and the test runner, without the test runner goodies.
  • ts-docs – same, on the test side, it is both an example parser and a test runner, without the test runner goodies. Stuck to TypeScript v4.

Installation

npm i -D generate-jsdoc-example-tests

# or directly via npx without installation:
npx generate-jsdoc-example-tests

Demo

You document your functions, methods, constants & classes, for coworkers or your future self, you get tests for free:

Documenting a function
// src/date-formatter.ts
/**
 * @example
 * ```ts
 * import { formatDateYear } from './date-formatter'
 * 
 * expect(formatDateYear(new Date('2026-01-01')).toBe('2026')
 * ```
 */
export function formatDateYear(date: Date) {…}

Generate tests:

npx gen-jet 'src/**' \
  --header 'import { expect, test } from "vitest"' \
  --test-file-extension '.example.test' # do not provide the `.ts` or `.js`

Generated test:

// src/date-formatter.example.test.ts
// DO NOT EDIT …
import { expect, test } from 'vitest' // the provided header
import { formatDateYear } from './date-formatter'

test('Example 1', () => {
  expect(formatDateYear(new Date('2026-01-01'))).toBe('2026')
})
Documenting a class
// src/date-formatter.ts
class DateFormatter {
  /**
   * @example
   * ```ts
   * import { DateFormatter } from './date-formatter'
   * 
   * const formatter = new DateFormatter()
   * expect(formatter.formatYear(new Date('2026-01-01')).toBe('2026')
   * ```
   */
  formatYear(date: Date) {…}
}

Generate tests:

npx gen-jet 'src/**' \
  --header 'import { expect, test } from "vitest"' \
  --test-file-extension '.example.test' # do not provide the `.ts` or `.js`

Generated test:

// src/date-formatter.example.test.ts
// DO NOT EDIT …
import { expect, test } from 'vitest' // the provided header
import { DateFormatter } from './date-formatter'

test('Example 1', () => {
  const formatter = new DateFormatter()
  expect(formatter.formatYear(new Date('2026-01-01'))).toBe('2026')
})
Documenting a constant
// src/date-formatter.ts
/**
 * @example
 * ```ts
 * import { formatDate, yearFormat } from './date-formatter'
 * 
 * const date = new Date('2026-01-01')
 * expect(formatDate(date, yearFormat)).toBe('2026')
 * ```
 */
export const yearFormat = 'YYYY'

export const formatDate = (date: Date, format: string): string => {…}

Generate tests:

npx gen-jet 'src/**' \
  --header 'import { expect, test } from "vitest"' \
  --test-file-extension '.example.test' # do not provide the `.ts` or `.js`

Generated test:

// src/date-formatter.example.test.ts
// DO NOT EDIT …
import { expect, test } from 'vitest' // the provided header
import { formatDate, yearFormat } from './date-formatter'


test('Example 1', () => {
  const date = new Date('2026-01-01')
  expect(formatDate(date, yearFormat)).toBe('2026')
})
Documenting an interface / a type
// src/date-formatter.ts
interface DateFormatter {
  /**
   * @example
   * ```ts
   * import { makeDateFormatter } from './date-formatter'
   * 
   * const formatter = makeDateFormatter()
   * expect(formatter.formatYear(new Date('2026-01-01')).toBe('2026')
   * ```
   */
  formatYear(date: Date): string
}

export const makeDateFormatter = (): DateFormatter => ({
  formatYear: () => {…},
})

Generate tests:

npx gen-jet 'src/**' \
  --header 'import { expect, test } from "vitest"' \
  --test-file-extension '.example.test' # do not provide the `.ts` or `.js`

Generated test:

// src/date-formatter.example.test.ts
// DO NOT EDIT …
import { expect, test } from 'vitest' // the provided header
import { makeDateFormatter } from './date-formatter'

test('Example 1', () => {
  const formatter = makeDateFormatter()
  expect(formatter.formatYear(new Date('2026-01-01'))).toBe('2026')
})

Usage

CLI

gen-jet: gen = generate ; jet = Jsdoc + Example + Tests.

$ npx gen-jet 'src/**'

# Usage with options:
$ npx gen-jet 'src/**' \
  --test-file-extension '.example.test' \
  --test-function-name 'it' \
  --header 'import { it, expect } from "vitest | jest | whatever"'
  --header 'import { myGlobalImport } from "~/some-global-stuff"'
  --include-example-containing expect,assert,assertStrict

# For a full CLI usage, checkout
$ gen-jet --help

Programmatic API

import { generateTests, type GenerateOptions } from 'generate-jsdoc-example-tests'

generateTests('./src/**')
  .then(() => console.info('tests generated'))
  .catch(console.error)

const myOptions: GenerateOptions = { … }

generateTests('./src/**', myOptions)
  .then(() => console.info('tests generated'))
  .catch(console.error)

Vitest

import { generateTests } from 'generate-jsdoc-example-tests'

generateTests('./src/**')
  .then(() => console.info('tests generated'))
  .catch(console.error)

generateTests('./src/**', {
  testFileExtension: '.generated.test', // default is '.example.test' ; do not provide `.ts` or `.js` !
  testFunctionName: 'it', // default is 'test'
  headers: ['import { it, expect } from "vitest"'],

  // keywords the JSDoc @example body must contain to be included in the generated tests.
  includeExampleContaining: ['expect('], // default is ['assert.', 'assert(', 'expect']
})
  .then(() => console.info('tests generated'))
  .catch(console.error)

FAQ

Which tests are included ?

There is a includeExampleContaining option, defaulted to ['expect(', 'assert.', 'assert(']. Any @example content containing expect(, assert. or assert( will have a generated test.

If you want to omit a test, you can omit it with @skipTest:

/**
 * @example This one is included because it contains `expect`
 * ```ts
 * import { myFn } from './my-fn'
 * expect(myFn()).toBe(true)
 * ```
 * @example This is omitted because there is no `expect` or `assert`
 * ```ts
 * myFn('toto') // invalid arg.
 * ```
 * @example this one is explicitly omitted {@skipTest}
 * ```ts
 * import { myFn } from './my-fn'
 * expect(myFn()).toBe(false)
 * ```
 */
export const myFn = () => true

Does it generate JS or TS files?

The test files are generated according to their source file:

  • if the source file is JS, the generated test file will be JS.
  • if the source file is TS, the generated test file will be TS.

I want to name my examples

Use the @exampleName inline tag:

/**
 * @example {@exampleName sum 4 and 5}
 * ```
 * import assert from "assert";
 * import { sum } from "./sample";
 *
 * assert.equal(sum(4, 5), 9);
 * ```
 */
export function sum() {…}

Generated test file:

import assert from "assert";
import { sum } from "./sample";

test("sum 4 and 5", () => {
  assert.equal(sum(4, 5), 9);
})

Thanks

I based this work upon Akito Ito's awesome tsdoc-testify and pushed it further with options and test runner interop.

Many MANY thanks to you Akito Ito πŸ™πŸ™

License

Same as the original one:

This project is licensed under the Apache License 2.0 License - see the LICENSE file for details

Contributing

First of all, thank you deeply if you want to participate. Please visit the contributing section for a detailed guide (getting started, roadmap).

If you like the project but don't have time to contribute, all good ! There are other ways to support the project and show your appreciation, which we would also be very happy about:

  • Star the project
  • Tweet about it
  • Refer this project in your project’s readme
  • Mention the project at local meetups and tell your friends/colleagues

Keywords

documentation

FAQs

Package last updated on 01 May 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts