From e14da1720329dd948d7eb9374588274bb1af3ec6 Mon Sep 17 00:00:00 2001 From: Casey Foster Date: Mon, 23 Sep 2013 14:57:16 -0500 Subject: [PATCH] Add test coverage, travis, 1.0.1 --- .travis.yml | 3 ++ Makefile | 12 +++++++ README.md | 2 ++ bower.json | 2 +- package.json | 10 ++++-- test/.jshintrc | 16 +++++++++ test/index.js | 79 +++++++++++++++++++++++++++++++++++++++++++ underscore-inherit.js | 27 ++++++--------- 8 files changed, 132 insertions(+), 19 deletions(-) create mode 100644 .travis.yml create mode 100644 Makefile create mode 100644 test/.jshintrc create mode 100644 test/index.js diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..244b7e8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - '0.10' diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4da265c --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +BIN=node_modules/.bin/ +MOCHA=$(BIN)mocha +WATCHY=$(BIN)watchy +TEST=$(MOCHA) --colors --recursive -R spec + +test-w: + NODE_ENV=test $(WATCHY) -w test,underscore-inherit.js -- $(TEST) + +test: + NODE_ENV=test $(TEST) + +.PHONY: test diff --git a/README.md b/README.md index 1bf5b04..8c9d3b6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ underscore-inherit ================== +[![Build Status](https://secure.travis-ci.org/caseywebdev/underscore-inherit.png)](http://travis-ci.org/caseywebdev/underscore-inherit) + Add constructor extensibility to Underscore.js. Install diff --git a/bower.json b/bower.json index 01d7066..82d918f 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "underscore-inherit", - "version": "1.0.0", + "version": "1.0.1", "main": "underscore-inherit.js", "dependencies": { "underscore": "x" diff --git a/package.json b/package.json index 6d09aa8..72d9c91 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "underscore-inherit", - "version": "1.0.0", + "version": "1.0.1", "author": "Casey Foster ", "main": "underscore-inherit", "repository": { @@ -8,6 +8,12 @@ "url": "https://github.com/caseywebdev/underscore-inherit" }, "devDependencies": { - "underscore": "x" + "chai": "x", + "mocha": "x", + "underscore": "x", + "watchy": "x" + }, + "scripts": { + "test": "make test" } } diff --git a/test/.jshintrc b/test/.jshintrc new file mode 100644 index 0000000..a00e62a --- /dev/null +++ b/test/.jshintrc @@ -0,0 +1,16 @@ +{ + "boss": true, + "browser": true, + "expr": true, + "eqnull": true, + "indent": 2, + "latedef": true, + "maxlen": 80, + "newcap": false, + "node": true, + "strict": false, + "sub": true, + "trailing": true, + "unused": true, + "white": true +} diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..9e4a0da --- /dev/null +++ b/test/index.js @@ -0,0 +1,79 @@ +var _ = require('underscore'); +require('..'); +var expect = require('chai').expect; + +describe('A simple "class"', function () { + var Klass = _.inherit({ + constructor: function () { this.instanceProp = 'a'; }, + protoProp: 'b' + }, { + staticProp: 'c' + }); + + it('is a function', function () { + expect(Klass).to.be.a('function'); + }); + + it('is inherited by its child', function () { + expect(new Klass()).to.be.instanceof(Klass); + }); + + it('copies static properties', function () { + expect(Klass).to.have.property('staticProp', 'c'); + }); + + it('copies prototype properties', function () { + expect(Klass.prototype).to.have.property('protoProp', 'b'); + }); + + it('equals the special constructor property', function () { + expect(Klass.prototype.constructor).to.equal(Klass); + }); + + it('invokes the constructor on instance creation', function () { + expect(new Klass()).to.have.property('instanceProp', 'a'); + }); +}); + +describe('Single inheritance', function () { + var KlassA = _.inherit({ + aProtoMethod: function () {} + }, { + aStaticMethod: function () {} + }); + + var KlassB = _.inherit(KlassA); + + it('works with instanceof', function () { + expect(new KlassB()).to.be.instanceOf(KlassA); + }); + + it("inherits the parent class's static methods", function () { + expect(KlassB).to.have.property('aStaticMethod'); + }); + + it("inherits the parent class's prototype methods", function () { + expect(KlassB.prototype).to.have.property('aProtoMethod'); + }); +}); + +describe('Multiple inheritance', function () { + var KlassA = _.inherit({ + theProtoMethod: function () {} + }); + + var KlassB = _.inherit({ + theProtoMethod: function () {} + }); + + var KlassC = _.inherit(KlassA, KlassB); + + it('works with instanceof', function () { + expect(new KlassC()).to.be.instanceOf(KlassA).and.instanceOf(KlassB); + }); + + it("inherits the most recent parent class's prototype methods", function () { + expect(KlassB.prototype).to.have + .property('theProtoMethod', KlassB.theProtoMethod); + }); +}); diff --git a/underscore-inherit.js b/underscore-inherit.js index 0e2e073..e722388 100644 --- a/underscore-inherit.js +++ b/underscore-inherit.js @@ -5,25 +5,20 @@ var node = typeof window === 'undefined'; var _ = node ? require('underscore') : window._; + var slice = [].slice; + // Define the mixin _.mixin({ inherit: function () { - var protoProps; - var staticProps; - var Parent = _.reduce(arguments, function (Parent, arg) { - if (_.isFunction(arg)) { - if (!Parent) return arg; - return _.inherit(arg, {constructor: Parent}); - } - if (_.isObject(arg)) { - if (!protoProps) { - protoProps = arg; - } else if (!staticProps) { - staticProps = arg; - } - } - return Parent; - }, null) || function () {}; + var args = slice.call(arguments); + var Parent; + while (_.isFunction(args[0])) { + var arg = args.shift(); + Parent = Parent ? _.inherit(arg, {constructor: Parent}) : arg; + } + if (!Parent) Parent = function () {}; + var protoProps = args[0]; + var staticProps = args[1]; // `Child` is the passed in `constructor` proto property // or a default function that uses `Parent`'s constructor