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 🙏

© 2024 – Pkg Stats / Ryan Hefner

minispec

v1.3.0

Published

Lightweight test/spec execution engine

Downloads

529

Readme

MiniSpec

Lightweight test/spec execution engine for TypeScript and JavaScript

MiniSpec is a lightweight test/spec execution engine for TypeScript and JavaScript, inspired by RSpec and minitest.

It works out-of-the-box with CommonJS, ESM and TypeScript.

Its purpose is to remain lightweight, without any runtime dependency and really low number of development dependencies.

Table of Content

Why another test/spec execution engine?

The idea of MiniSpec came from the need to write some unit-tests for a tiny library written in TypeScript. All testing framework were pretty big - with a lot of dependencies - and may not work well out-of-the-box with TypeScript.

MiniSpec goal is to remain lightweight, without runtime dependency. Its main purpose is to add a bunch of tests to small JavaScript or TypeScript projects.

Its name comes from the combination of minitest, and RSpec. Minitest for the idea of having a small and easy to maintain test/spec engine. RSpec for the spec syntax and for some output formats.

Why does weight matter?

Less dependencies and a lightweight library means less resources consumed while downloading it and executing it. It also reduces the potential attack surface.

That means also fewer features. That is why MiniSpec purpose is to be used with small projects, which do not need advanced testing capabilities offered by more popular alternatives.

What's new in version 1.3.0

While full changelog is available in the repository, here's what's new in v1.3.0:

  • Added

    • Official support for Chai Assertion Library: while Chai was already working fine with MiniSpec, its support is now enforced via automated integration tests. That means also that if you are facing any issue using Chai with MiniSpec, you can report it and we'll do our best to fix it.
    • Support for Node.js v22
  • Changed

    • [Internal] Bump development dependencies
    • [Internal] Usage of npm workspaces to manage examples and integration tests
    • Bump dependencies from the various examples
  • Deprecated

    • Support for Node.js v16 is deprecated and will be dropped with next major version of MiniSpec: v2.0

Usage

Installation

To install MiniSpec, add it to your dev dependencies:

$ npm install --save-dev minispec

or with yarn:

$ yarn add minispec --dev

Check install

To make sure it is working as expected, create a file named validate_minispec_install.mjs in your project root directory:

// validate_minispec_install.mjs

import assert from 'assert'
import MiniSpec, { describe, it } from 'minispec'

describe('minispec', async () => {
  it('is working', async () => {
    assert.ok(true)
  })
})

MiniSpec.execute()

Then run the following:

$ node validate_minispec_install.mjs

The expected output should look like the following:

minispec
  is working

Finished in 3 milliseconds (discovering took 1 milliseconds, execution took 2 milliseconds)
1 test, no failure 👏

Congrats, MiniSpec is working fine! You can delete the file validate_minispec_install.mjs and start writing your own specs.

Writing tests

Due to its nature, MiniSpec comes with less magic than other test framework. You'll have to write a little bit of code to set it up. But don't worry, nothing complicated: only basic JavaScript/TypeScript.

The big picture

In a typical setup, you'll have an entrypoint for MiniSpec which will be responsible for loading MiniSpec, importing your tests, configuring your test environment, then executing the tests.

The following examples illustrates it in TypeScript, and in JavaScript using es Modules and CommonJS

In TypeScript

// ./specs/minispec_entrypoint.ts

import MiniSpec from 'minispec'

import './calculator_spec'

MiniSpec.execute()

Then your test files may look like the following:

// ./specs/calculator_spec.ts

import assert from 'assert/strict'
import { describe, context, beforeEach, it } from 'minispec'

import Calculator from '../src/calculator'

describe('Calculator', async () => {
  let calculator: Calculator

  beforeEach(async () => {
    calculator = new Calculator()
  })

  describe('.sum(a, b)', async () => {
    context('when a and b are valid numbers', async () => {
      const a = 40
      const b = 2

      it('returns the sum of a and b', async () => {
        assert.equal(calculator.sum(a, b), 42)
      })
    })
  })
})

Assuming the following calculator:

// ./src/calculator.ts

export default class Calculator {
  constructor() {}
  sum(a: number, b: number): number {
    return a + b
  }
}

You can then build and run your tests:

$ npx tsc src/*.ts specs/*.ts --module CommonJS --esModuleInterop true --rootDir "." --outDir "./dist"
$ node ./dist/specs/minispec_entrypoint.js

You can also make it part of your package scripts in your package.json:

{
  "scripts": {
    "build:specs": "tsc src/*.ts specs/*.ts --module CommonJS --esModuleInterop true --outDir './dist'",
    "test": "npm run build:specs && node ./dist/specs/minispec_entrypoint.js"
  }
}

Now you can run your tests using:

$ npm test

MiniSpec is also compatible with EcmaScript modules (es5, es6, esnext, ...), and ts-node. It relies only on your own usage and configuration of TypeScript.

Using ECMAScript modules (esm)

// ./specs/minispec_entrypoint.js

import MiniSpec from 'minispec'

import './calculator_spec.js'

MiniSpec.execute()

Then your test files may look like the following:

// ./specs/calculator_spec.js

import assert from 'assert/strict'
import { describe, context, beforeEach, it } from 'minispec'

import Calculator from '../src/calculator.js'

describe('Calculator', async () => {
  let calculator

  beforeEach(async () => {
    calculator = new Calculator()
  })

  describe('.sum(a, b)', async () => {
    context('when a and b are valid numbers', async () => {
      const a = 40
      const b = 2

      it('returns the sum of a and b', async () => {
        assert.equal(calculator.sum(a, b), 42)
      })
    })
  })
})

Assuming the following calculator:

// ./src/calculator.js

export default class Calculator {
  constructor() {}
  sum(a, b) {
    return a + b
  }
}

You can then run your tests:

$ node ./specs/minispec_entrypoint.js

You can also make it part of your package scripts in your package.json:

{
  "scripts": {
    "test": "node ./specs/minispec_entrypoint.js"
  }
}

Now you can run your tests using:

$ npm test

Using CommonJS

// ./specs/minispec_entrypoint.js

const MiniSpec = require('minispec').default

require('./calculator_spec.js')

MiniSpec.execute()

Then your test files may look like the following:

// ./specs/calculator_spec.js

const assert = require('assert').strict

const { describe, context, beforeEach, it } = require('minispec')
const Calculator = require('../src/calculator.js').default

describe('Calculator', async () => {
  let calculator

  beforeEach(async () => {
    calculator = new Calculator()
  })

  describe('.sum(a, b)', async () => {
    context('when a and b are valid numbers', async () => {
      const a = 40
      const b = 2

      it('returns the sum of a and b', async () => {
        assert.equal(calculator.sum(a, b), 42)
      })
    })
  })
})

Assuming the following calculator:

// ./src/calculator.js

exports.default = class Calculator {
  constructor() {}
  sum(a, b) {
    return a + b
  }
}

You can then run your tests:

$ node ./specs/minispec_entrypoint.js

You can also make it part of your package scripts in your package.json:

{
  "scripts": {
    "test": "node ./specs/minispec_entrypoint.js"
  }
}

Now you can run your tests using:

$ npm test

Picking an assertion library

MiniSpec should work well with any assertion library. Yet it provides official support for the Node.js built-in assert one, and also for chai.

Node.js built-in assert

The Node.js built-in assertion library is simple, yet far enough for small projects where MiniSpec may be used. Remember: MiniSpec is designed for small projects which just requires a bunch of tests. Node.js assert library is also perfect in such case!

Chai Assertion Library

Chai is a BDD/TDD assertion library which remains relatively lightweight and offer more assertions, but mostly 3 styles: assert, expect and should.

MiniSpec officially supports Chai since version 1.3.0. It means that if you are facing issues integrating Chai with MiniSpec, you can report it and we'll do our best to find a fix or a workaround.

More documentation

To go further, you can follow the documentation: