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

fh-mocks

v0.1.1

Published

Mocks for the fh-js-sdk to enable unit testing of application logic.

Downloads

25

Readme

FeedHenry Mocks

build-status version

A library that enables you to mock out APIs from the FeedHenry JS SDK. This enables unit testing of application logic without the need to actually run the SDK code which may be impractical or impossible for testing purposes.

Usage

To use this mocking library simply include it in a script tag in a custom test HTML file or inject it using Karma (which is a much better idea). Alternatively you can run your tests in a Node.js environment since this module will create a $fh global on either window or global depending on where you're running it, a browser or Node.js respectively. See here for an example of Node.js tests for a library that is actually meant for a browser!

This should be included instead of or after the standard feedhenry.js SDK script when testing.

What's nice about this is that you can write all tests in a blocking manner which keeps things pretty simple. You can write them using non-blocking syntax via the usual Jasmine/Mocha done callback (these are the only two I'm familiar with) if required too, just call the mock flush method when appropriate.

Example


'use strict';

var assert = require('assert');
// var fh = require('fh-js-mocks') <-- Possible with browserify

var USER = 'johndoe',
	PASS = 'ismaithliomcácamilis';

describe('Some Controller/Model', function () {
	
	afterEach(function () {
		// Makes sure we're using and responding to all request planned per test
		// If you define an expect and never send the corresponding 
		// request ($fh.act) then verifyNoOutstandingExpectation will throw an
		// error. The same goes for verifyNoOutstandingRequest expect it throws
		// for requests that have no expectation to match
		$fh.act.verifyNoOutstandingRequest();
		$fh.act.verifyNoOutstandingExpectation();

		// This is optional. It will restore the original act function
		// if you have included feedhenry.js
		$fh.restoreOriginalApi('act');
	});

	beforeEach(function () {
		// Create a shim function to replace the regular before running tests
		$fh.createApiShim('act');
	});


	describe('#login', function () {

		it('Should successfully login.', function () {
			// We tell $fh.act that a request with these parameters should be
			// expected to be called.
			$fh.act.expect({
				act: 'login',
				req: {
					u: USER,
					p: PASS
				}
			})
			// The set response function takes two args. 
			// The first arg, if not null will cause the error/fail callback
			// to be called with the given value. The second arg will be the 
			// result passed to the success callback but will only be triggered 
			// if the first arg is null
			.setResponse(null, {
				session: 'e4b6f7cfbe45a24e4773c6c2f59a0c41'
				data: {
					user: USER,
					dob: '1985-08-13'
				}
			});

			// The login function uses $fh.act internally
			MyController.login(USER, PASS, function (err, res) {
				assert.equal(err, null);
				assert(res);
				assert.equal(typeof res.session, 'string');
				// etc...
			});

			// Respond to any requests we've queued to $fh.act so far.
			// This will trigger the callback provided to MyController.login
			$fh.act.flush();
		});

	});

});

API

This library mimics the normal FeedHenry JavaScript SDK. As you might be aware the majority of API functions work like so:

$fh.someApi(options, successCallback, failCallback);

This library allows you to override existing implementations, and will create one if none exists. For example this will replace/create the $fh.act API:

$fh.createShim('act');

MockApiInstance

Created using $fh.createApiShim(name). Works just like a regular $fh API. Well, almost like a regular API. It's still a same old function definition you know and love: $fh.someApi(opts, success, fail). What's different is that it has some new functions appended as described here, and demonstrated in the examples.

MockApiInstance.expect(input)

The expect function tells our mock API service to expect a specific input and returns a MockApiResponder that allows us to configure a response scenario for the given input as detailed below.

MockApiInstance.flush([count])

Respond to count calls that have been queued to the API mock. Calls are only responed to if the same parameters it provided were given via an expect. The parameter comparison is done by using JSON.stringify on your inputs passed to $fh.shim.expect(input) and $fh.shim(inputs, success, fail).

You'll probably not need to supply the optional count argument often, perhaps even never.

MockApiInstance.verifyNoOutstandingRequest()

Verify that all calls to your shim were satisfied. Can be called in an afterEach hook to ensure you're cleanly responding to each call.

MockApiInstance.verifyNoOutstandingExpectation()

Verify that all expectations had a request made for them. Can be called in an afterEach hook to ensure you're not defining unnecessary expectations and that those you do declare are utilised.

MockApiResponder

An instance of this is returned from $fh.shim.expect. This class should be used to configure responses to your SDK inputs. The only function you should need to use is setResponse unless certain edge cases arise that require otherwise.

setResponse(err, res)

Configure the response that should be returned when inputs to expect match the input you provide to $fh.shim. Providing a non null value as the first parameter will cause the error callback you provided to the SDK to be called upon flushing the api call queue using flush. See the example below:


describe('Test Our Push Module', function () {
	afterEach(function () {
		$fh.push.verifyNoOutstandingRequest();
		$fh.push.verifyNoOutstandingExpectation();
		$fh.restoreOriginalApi('push');
	});

	beforeEach(function () {
		// Create a shim function for $fh.push
		$fh.createApiShim('push');
	});

	it('Should handle failure and return SDK error', function () {
		var ERR_CODE = 'push_nosupport';

		var responder = $fh.push.expect({
			act: 'register'
		});

		responder.setResponse(ERR_CODE, null);

		// Uses $fh.push internally
		PushModule.register(funcion (sdkError, result) {
			assert.equal(sdkError, ERR_CODE);
		});

		$fh.push.flush();
	});

	it('Should handle failure and return SDK error', function () {
		var FAKE_TEST_RES = {
			deviceToken: '12345890'
		};

		var responder = $fh.push.expect({
			act: 'register'
		});

		responder.setResponse(null, FAKE_TEST_RES);

		// Uses $fh.push internally
		PushModule.register(funcion (sdkError, result) {
			assert(result)
			assert.equal(result.deviceToken, FAKE_TEST_RES.deviceToken);
		});

		$fh.push.flush();
	});
});