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

fzkes

v0.15.0

Published

A faking library

Downloads

24

Readme

fzkes

A faking library

I must immediately apologize for the name; it is a horrible pun combining fzk (a shortening of the name of my company) and fakes. But it does have a nice ring to it, and I want it to be short and unique. So there it is.

How to use

Creating fakes

var fzkes = require('fzkes')

// Creating a stand-alone fake, great for use as a callback
var fake = fzkes.fake()

// For overriding an original function, great for restoring later
var fs = require('fs')
fzkes.fake(fs, 'readFile')

// For faking all functions on an object
fzkes.fakeAll(fs)

fakeAll

The fzkes.fakeAll() function can take an options-dictionary, allowing for overriding the default action. The options are:

  • callsOriginal: The default. fake.callsOriginal() is evoked on all fakes.
  • none: No action is taken on the fakes.
  • throws: A 'Fake not overridden' exception will be evoked on all fakes.

All fakes can of course be overridden later on, the default is just what should happen out-of-the-box.

Resetting fakes

Resetting a fake (fake.reset()) will set its internal state to what it was when it was new.

It is possible to reset all fakes by calling fzkes.reset() or scope.reset().

Restoring original functions

There are three ways to easily doing this, depending on the scope:

  1. Restoring a single fake: fake.restore()
  2. Restoring all fakes across the board: fzkes.restore()

The last is a bit more tricky; A sub-scope can be creating by calling fzkes.scope(). The scope have all methods (except chai) that the original fzkes object have, except the restore() function on a scope only affects fakes created within that scope.

Injecting data

fake.returns('abc')
fake.throws(new Error('some error'))
fake.calls(function() { console.log('was called') })

// If it replaced a function on an object:
fake.callsOriginal()

// Conditional injects
fake.withArgs(1,2).returns(3)
fake.withArgs(1,2).callsOriginal()

Each action (returns, throws, calls, etc) returns the fake, to make it easier to assign to return values and the like:

fake.returns({
	a: fzkes.fake('a').returns(3),
	b: fzkes.fake('b').throws()
})

It can also chain the withArgs() automatically:

var fake = fzkes.fake('name')
	.returns(1)
	.withArgs(1,2).returns(3)
	.withArgs(1,3).returns(4)
	.withArgs(1,4).throws(new Error('some error'))
fake(1,1) // => 1
fake(1,2) // => 3
fake(1,3) // => 4
fake(1,4) // => throws

Advanced withArgs

There is a more advanced form of withArgs called withComplexArgs. It allows for skipping arguments entirely, as well as defining regular expressions to validate against strings.

var fake = fzkes.fake('name')
	.returns(1)
	.withComplexArgs(null, { value: 2 }).returns(2)
	.withComplexArgs({ regex: /ab?c/ }).returns(3)

fake(1, 1) // => 1
fake(1, 2) // => 2
fake('a', 2) // => 2
fake('abc') // => 3
fake('ac') // => 3

Calling callbacks

There is a built-in helper for calling callbacks: callsArg. If the callback throws an exception, the fake with throw it as well.

It can take the following options:

  • notify: A function to notify whenever the fake is called. It is called as function(error, returnValue), where error is whatever the callback threw, and returnValue is what the callback returned. If async is false, the fake will return whatever the notify function returns.

    This option is also perfect for mocha style async handlers.

  • returns: A value to return whenever the fake is called. This takes presedence over the return-value of notify, but exceptions still triumph.

  • now: A flag that determines if the action should occur for future calls or for the first unhandled call. This will throw if the fake have no unhandled calls.

  • async: A flag determining if the callback should be called immediately or in the next tick (which would simulate an async call).

  • arg: The argument to call. This can be the parameter index (0-n), 'first' or 'last'. It defaults to 'last'.

  • arguments: An array of the arguments to pass to the callback.

Examples follow:

// Default is calling the last function found, node-style
fake.callsArg()

// It can be controlled
fake.callsArg({ arg: 'first' })
// 0-indexed argument list
fake.callsArg({ arg: 1 })

// It defaults to calling the callback immediately, but this can be changed
fake.callsArg({ async: true })

// Default is no parameters to the callback, but these can be controlled
fake.callsArg({ arguments: [ 1, 2 ] })

Emulating calls after they have been called

Sometimes, it is not feasible to prepare the fake properly; in these cases, emulating the call after the fact makes the code much better.

fzkes supports this as an option for the fake.calls(), fake.callsArg() and fake.callsOriginal() functions.

The code would look as the following:

fake(1,2,3)

fake.calls(fn, { now: true })
fake.callsOriginal({ now: true })
fake.callsArg({ now: true })

It works with all other options on the fake.callsArg() call.

It forwards the next unhandled call as it appeared on the fake, and throws an exception if there are no unhandled calls:

fake(1,2,3)
// Goes through
fake.callsOriginal({ now: true })

try {
	fake.calls(fn, { now: true })
} catch(e) {
	// e.message would say that fake had no unhandled calls.
}

If any of the functions was set up in advance, calls are not considered unhandled, and any call with { now: true } will throw an exception. To begin building unhandled calls, make a fake.calls(null) invocation.

fake.callsOriginal()
// this call is handled immediately
fake()
expect(function() {
	fake.callsOriginal({ now: true })
}).to.throw()

// resetting the expectations
fake.calls(null)

// it now works again
fake()
fake.callsOriginal({ now: true })

Asserting

fake.wasCalled()
fake.wasCalledWith(1, 2, 3)
fake.wasCalledWithExactly(1, 2, 3)
fake.callCount == 2

Using with chai

chai.use(fzkes)
fake.should.have.been.called // at least once
fake.should.have.been.called(2) // precisely 2 times
fake.should.have.been.calledWith(1,2,3)

Running in the browser

Use a tool like browserify or webpack to generate a browser-compatible version of the tests. Then simply follow the guide above for setting it up and interacting with it.

NOTE: Pre v0.15, the package built a browser-version always. This task have now been delegated to the consumer of the library.