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

ng-test

v0.2.1

Published

Less boilerplatey more declarativy Karma + Jasmine tests for your ng-di or angular.js code

Downloads

6

Readme

ngTest

less boilerplatey more declarativy Karma + Jasmine tests for your ng-di or angular.js code.

Use It

just load ngTest.js in your karma tests and call the ngTest global function.

ngTest does code generation of ng-di and Angular specific Jasmine tests per the following spec.

Defining tests

ngTest(spec, debug) takes an object that defines a series of Jasmine tests, and an optional debug boolean.

To define the initial 'describe' function provide a string key for the description. The value can be a traditional describe function.

ngTest({
	"This is my describe block": function() {
		// just your standard describe function here
	}
});

The value can also be an array of the following values all of which are optional and can be used multiple times:

Strings

Strings define either angular modules to load or dependencies to inject. The difference is determined by the convention of appending ":" to module names e.g. "myApp:" Also remember to use the fully qualified angular name for dependencies e.g. 'momentFormatFilter' instead of just 'momentFormat'

ngTest({"Testing my Module": ["myModule:", "myDependency", {
	"should work": function() {
		// put expect code here
	}}]
});

Here's an example showing how modules that have the same name as a dependency can be handled with the '+' suffix. In this case the 'titleService:+' will cause the titleService module to be loaded and will inject the titleService dependency. When using the '+' suffix the ':' is optional but I find it more readable with both.

ngTest({
	"titleService": ["titleService:+", "$document", {

		"should set a title without a suffix": function() {
			var title = "new title";
			titleService.setTitle(title);
			return expect(titleService.getTitle()).toEqual(title);
		},

		"should allow specification of a suffix": function() {
			var suffix = " :: new suffix";
			titleService.setSuffix(suffix);
			return expect(titleService.getSuffix()).toEqual(suffix);
		},

		"should set the title, including the suffix": function() {
			var title = "New Title",
				suffix = " :: new suffix";

			titleService.setSuffix(suffix);
			titleService.setTitle(title);

			return expect(titleService.getTitle()).toEqual(title + suffix);
		}
	}]
});

The generated Code looks like this

describe('titleService', function () {

	beforeEach(function () {
		module('titleService');
	});

	var titleService, $document;
	beforeEach(inject(function (_titleService_, _$document_) {
		titleService = _titleService_;
		$document = _$document_;
	}));

	it('should set a title without a suffix', function () {
		var title = "new title";
		titleService.setTitle(title);
		return expect(titleService.getTitle()).toEqual(title);
	});

	it('should allow specification of a suffix', function () {
		var suffix = " :: new suffix";
		titleService.setSuffix(suffix);
		return expect(titleService.getSuffix()).toEqual(suffix);
	});

	it('should set the title, including the suffix', function () {
		var title = "New Title",
			suffix = " :: new suffix";

		titleService.setSuffix(suffix);
		titleService.setTitle(title);

		return expect(titleService.getTitle()).toEqual(title + suffix);
	});

});

Closure Variables

You may want to define a value once and have it available to all your tests through a closure reference. This is no problem. Simply inline the name of the variable you want appended with = like so:

ngTest({"Example Test": [
	"mySharedData=",
	function before() {
		mySharedData = {
			items: [
				{id: 0, name: "test"},
				{id: 1, name: "test1"},
				{id: 2, name: "test2"}
			],
			selectedId: 1
		};
	},
	{
		"Should have access to mySharedData": function() {
			expect(mySharedData.items.length).toBe(3);
		}
	}
]});

output looks like this

describe('Example Test', function () {
	var mySharedData;
	beforeEach(function before() {
		mySharedData = {
			items: [
				{id: 0, name: "test"},
				{id: 1, name: "test1"},
				{id: 2, name: "test2"}
			],
			selectedId: 1
		};
	});
	it('Should have access to mySharedData', function () {
		expect(mySharedData.items.length).toBe(3);
	});
});

Anonymous Functions

The first will become a beforeEach, the second will become an afterEach. If you need more than that or want something more self-documenting see Named Functions below.

ngTest({"Testing my Module": ["myModule:", "myDependency",
	function() {
		// do before each
	},
	function() {
		// do after each
	}, {
		"should work": function() {
			// put expect code here
		}
	}]
});

Named Functions

Use 'before' or 'after' as the prefix for the function name. This allows for multiple and self documenting beforeEach and afterEach functions if you want to have multiple.

ngTest({"Testing my Module": ["myModule:", "myDependency",
	function before() {
		// do before each
	},
	function beforeTwo() {
		// do before each
	},
	function after() {
		// do after each
	}, {
		"should work": function() {
			// put expect code here
		}
	}]
});

Named functions that are not prefixed with 'before' or 'after' get in-lined into the describe block and will be ready for use in your tests.

ngTest({"Testing my Module": ["myModule:", "myDependency",
	function times2(n) {
		return n*2;
	}, {
		"should work": function() {
			expect(times2(5)).toBe(10);
		}
	}]
});

Objects

A nested 'describe' or 'it' function. The difference is determined by the convention of 'it' function keys starting with 'should' There are no changes to the 'it' function, provide your standard tests here.

ngTest({"Filters: common filters": ["myApp:", "filters:", {

	"Filter: momentFormat": ["momentFormatFilter",{
		"should convert a date string to a formatted date string": function() {
			expect(momentFormatFilter("Tue Aug 27 2013 14:04:12 GMT-0500 (CDT)", "MM/DD/YY")).toBe("08/27/13");
		}
	}],

	"Filter: momentAgo": ["momentAgoFilter", {
		"should convert a date string to an ago string": function() {
			expect(momentAgoFilter("Tue Aug 27 2013 14:04:12 GMT-0500 (CDT)", "MM/DD/YY")).toEndWith(" ago");
		}
	}]

}]});

If you provide the debug boolean in the above example it will log the generated code which looks like this:

describe("Filters: common filters", function() {

	beforeEach(function() {
		module('myApp');
		module('filters');
	});

	describe("Filter: momentFormat", function() {

		var momentFormatFilter;
		beforeEach(inject(function(_momentFormatFilter_) {
			momentFormatFilter = _momentFormatFilter_;
		}));

		it("should convert a date string to a formatted date string", function() {
			expect(momentFormatFilter("Tue Aug 27 2013 14:04:12 GMT-0500 (CDT)", "MM/DD/YY")).toBe("08/27/13");
		});

	});

	describe("Filter: momentAgo", function() {

		var momentAgoFilter;
		beforeEach(inject(function(_momentAgoFilter_) {
			momentAgoFilter = _momentAgoFilter_;
		}));

		it("should convert a date string to an ago string", function() {
			expect(momentAgoFilter("Tue Aug 27 2013 14:04:12 GMT-0500 (CDT)", "MM/DD/YY")).toEndWith(" ago");
		});

	});

});

compileWithScope util

ngTest also provides a handy util for testing directives to help reduce the boilerplate for compiling a directive with a new scope.

Simply call the compileWithScope(spec) function where spec is an object with an 'html' string property and a 'scope' property that is a plain old js object containing the values you would like on your scope. If no scope object is provided the html will be compiled with a new scope that is empty.

Usage looks like this

ngTest({"SimplePicker - Element directive for a basic skinnable widget": [
	"simplePicker:",
	"templates-common:",
	"filters:",
	{
		"Should create a picker widget": function() {
			var directive = compileWithScope({
				html: '<simple-picker id="myPicker" items="clients" selected-id="selectedId"/>',
				scope: {
					clients: [
						{id: 0, name: "test"},
						{id: 1, name: "test1"},
						{id: 2, name: "test2"}
					],
					selectedId: 1
				}
			});

			// compileWithScope returns an object with the following members
			dump(directive.el, directive.scope, directive.compiled);

			expect($(directive.el).attr("id")).toBe("myPicker");
			expect($("a.pickerSelection", directive.el).text()).toBe("test1");
			expect($("ul li", directive.el).length).toBe(3);
		}
	}
]});

Which will output the following code.

describe('SimplePicker - Element directive for a basic skinnable widget', function () {

	beforeEach(function () {
		module('simplePicker');
		module('templates-common');
		module('filters');
	});

	var $compile, $rootScope;
	beforeEach(inject(function (_$compile_, _$rootScope_) {
		$compile = _$compile_;
		$rootScope = _$rootScope_;
	}));

	function compileWithScope(spec) {

		var ret = {};

		// create a scope
		ret.scope = $rootScope.$new();

		// copy provided scope vals to our new scope
		if (spec.scope) {
			angular.extend(ret.scope, spec.scope);
		}

		// get the jqLite or jQuery element
		ret.el = angular.element(spec.html);

		// compile the element into a function to
		// process the view.
		ret.compiled = $compile(ret.el);

		// run the compiled view.
		ret.compiled(ret.scope);

		// call digest on the scope!
		ret.scope.$digest();

		return ret;
	}

	it('Should create a picker widget', function () {
		var directive = compileWithScope({
			html: '<simple-picker id="myPicker" items="clients" selected-id="selectedId"/>',
			scope: {
				clients: [
					{id: 0, name: "test"},
					{id: 1, name: "test1"},
					{id: 2, name: "test2"}
				],
				selectedId: 1
			}
		});

		// compileWithScope returns an object with the following members
		dump(directive.el, directive.scope, directive.compiled);

		expect($(directive.el).attr("id")).toBe("myPicker");
		expect($("a.pickerSelection", directive.el).text()).toBe("test1");
		expect($("ul li", directive.el).length).toBe(3);
	});
});

Support for ngExample

ngExample uses ngTest to help with some test rewriting it needs to do, functionality to support this is baked into ngTest. Specifically this includes:

  • automatic injection of the ngExampleApp module as needed
  • blocking the loading of modules where the module name matches the following regex /template|.tpl.html/i
  • Support for deferred injection of test before and after functions the testInjections global. Anyone can use this feature by defining either or both the before and after members of this object as arrays of before each and after each functions that will be added to the top of the first describe block.

Support for React.js

basically this means adding the following handy global variable to the page if ReactTestUtils are loaded.

ReactTestUtils = React.addons.ReactTestUtils;