Node TAP 21.0.1

tap Sinon Plugin (optional)

@tapjs/sinon

A tap plugin for using sinon

A t.sinon property is added to tests, which is a Sinon sandbox for that single test. When the test is completed, the sandbox is torn down automatically, but you can also of course call t.sinon.restore() to remove all fakes and spies and such.

Also adds a sinon property to the test config, which can be used to configure the sinon property. If no config is specified, then it uses sinon.defaultConfig, which enables everything.

Installation#

Install @tapjs/sinon, and add '@tapjs/sinon' to your plugin config list in package.json or .taprc.

# install the plugin:
npx tap plugin add @tapjs/sinon

# or, manually:
npm install --save-dev @tapjs/sinon

# add '@tapjs/sinon' to plugins list
vim .taprc

# rebuild tap with the plugin applied
npx tap plugin build

If you're using this, you may want to disable the built-in @tapjs/intercept plugin, because it has a very similar use case, but is much more limited in scope than sinon.

tap plugin rm @tapjs/intercept

Usage#

Just use the t.sinon property, it's a sinon sandbox and it automatically cleans itself up when the test is done.

import t from 'tap'

const myAPI = { hello: () => {} }
t.test('some child test', t => {
  // this stub call is only relevant within this test
  t.sinon.stub(myAPI, 'hello')
  myAPI.hello()
  t.sinon.assert.calledOnce(myAPI.hello)
  t.end()
})

t.test('another test', async t => {
  // myAPI.hello is no longer a sinon stub
})

t.test(
  'sinon with a config object',
  {
    sinon: {
      injectInto: null,
      useFakeTimers: true,
    },
  },
  async t => {
    // t.sinon only has the configured setup here
  },
)

Using with Fake Timers#

Sinon does not behave properly if fake timers are assigned to the same global object more than once, resulting in a 'Can't install fake timers twice on the same global object.' error.

By default, this library sets { useFakeTimers: false } in the options to avoid this. You can enable fake timers in a given test by setting it in the sinon option as shown in the examples above, but note that it can only be used in a single place in a test heirarchy.

For example:

// ok, works fine
t.test(
  'fake timers test one',
  { sinon: { useFakeTimers: true } },
  t => {
    t.test('child test', t => {
      // etc.
    })
  },
)
t.test(
  'second fake timers test',
  { sinon: { useFakeTimers: true } },
  t => {
    // etc.
  },
)

// this, however, does not work:
t.test('parent', { sinon: { useFakeTimers: true } }, t => {
  t.test('child', { sinon: { useFakeTimers: true } }, t => {
    // will throw an error
  })
})