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

funjector

v3.1.0

Published

dependency injection for functional paradigm

Downloads

11

Readme

Funjector

Build Status npm

The purpose of this module was to create a simple dependency injection module for functions. This makes writing unit tests a breeze.

Installation

npm i funjector --save

Example

Say I have a scenario where there is a function A that I want to test, which internally calls another global function B. For the sake of simplicity lets also assume that both the functions a truly pure.

function B (x) {
  return x * 100
}

function A (x, y) {
  return B(x + y)
}

There are multiple ways you can test function A()

  • Without mocking B: In this case you don't mock the function B() and let A use the global B function. In this approach you end up testing the B function as well. This is fine if the function is simple and is only being used by A. If the function is complex and say performs some time consuming operations, then its always better to mock B.
  • Mocking B Globally: So assuming that B isn't a simple function and must be mocked we can globally mock B. Global mocking comes with its own set of overheads such reseting the Mocked function after every test. There are quite a few libraries that will help you mock and reset functions/modules globally. Most of them are quite essentially hacks as they bind themselves to env globals such as require and process.
  • Mocking B Locally: This is exactly what one should be doing. We need to re-write A such that B is a param to A.
function B (x) {
  return x * 100
}

function A (B, x, y) {
  return B(x + y)
}

A(B, 10, 20) // Sample Call for function A

Though this seems like a good solution but it comes with a major drawback — Wherever I am going to use A, I will have to pass an additional param B to it.

This can get out of control pretty easily —

function C (x) {
  return x - 1
}

function B (C, x) {
  return C(x * 100)
}

function A (B, C, x, y) {
  return B(C, x + y)
}

A(B, C, 10 ,20)

As you can, though A only needs three params viz — B, x, y I have to pass C because internally B needs C! This is still an overly simplified version of issues one might face.

With funjector


import {partial, call} from 'funjector'

function C (x) {
  return x - 1
}

// Binds the function B with C as the first param
const B = partial(function (C, x) {
  return C(x * 100)
}, C)

// Binds the function A with B as the first param
const A = partial(function (B, x, y) {
  return B(x + y)
}, B)

A(10, 20) // Calls the partialized version of the function
call(A, i => i + 1, 10, 20) // Calls the original function A with a custom implementation of B

API

partial(func, *args)

Creates a function that calls func with args arguments prepended to those provided to the new function.

import {partial} from 'funjector'
const a = partial((x, y) => x * y, 10)
a(3) // OUTPUTS: 30
a(4) // OUTPUTS: 40

call(func, *args)

calls a partialized function returned by partial(), with the passed args ignoring all the arguments that were passed as the bindings.

import {call, partial} from 'funjector'
const a = partial((x, y) => x * y, 10)
call(a, 9, 3) // OUTPUTS: 27 and not 30
call(a, 9, 4) // OUTPUTS: 36 and not 40

callWith(func, context, *args)

exactly like call() except that the second param is used as the context with which the function func is invoked.

SKIP

a placeholder that can be used with the function partial() to selectively control the order of arguments that are being passed the function.

import {SKIP, partial} from 'funjector'
const a = partial((a, b, c, d) => [a, b, c, d], 1, SKIP, SKIP, 4)
a(2, 3) // OUTPUTS:  [1, 2, 3, 4]