diff --git a/.gitignore b/.gitignore index 3c3629e..9ac76a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +tests/coverage diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 0000000..4599bc7 --- /dev/null +++ b/.jscsrc @@ -0,0 +1,11 @@ +{ + "excludeFiles": [ + ".git/**", + "node_modules/**", + "tests/coverage/**" + ], + "fileExtensions": [".js"], + "preset": "google", + + "disallowMultipleVarDecl": null +} diff --git a/.travis.yml b/.travis.yml index 6e5919d..890d914 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ language: node_js node_js: - "0.10" +after_success: +- npm run coveralls diff --git a/README.md b/README.md index 69d281d..03e38a8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# react-minimal-router [![Build Status](https://travis-ci.org/skidding/react-minimal-router.svg?branch=master)](https://travis-ci.org/skidding/react-minimal-router) +# react-minimal-router [![Build Status](https://travis-ci.org/skidding/react-minimal-router.svg?branch=master)](https://travis-ci.org/skidding/react-minimal-router) [![Coverage Status](https://coveralls.io/repos/skidding/react-minimal-router/badge.svg)](https://coveralls.io/r/skidding/react-minimal-router) Bare router for React components, using query string as props. ``` diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..a5cd533 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,30 @@ +module.exports = function(config) { + config.set({ + basePath: 'tests/', + browsers: ['PhantomJS'], + coverageReporter: { + type: 'lcov', + dir: 'coverage/' + }, + files: [ + '**/*.js' + ], + frameworks: ['mocha', 'chai', 'sinon-chai'], + preprocessors: { + '**/*.js': ['webpack'] + }, + reporters: ['mocha', 'coverage'], + webpack: { + module: { + postLoaders: [{ + test: /\.js$/, + exclude: /(node_modules|tests)\//, + loader: 'istanbul-instrumenter' + }] + } + }, + webpackMiddleware: { + noInfo: true + } + }); +}; diff --git a/package.json b/package.json index c96fd88..cfe1f54 100644 --- a/package.json +++ b/package.json @@ -1,23 +1,39 @@ { "name": "react-minimal-router", - "version": "0.1.0", + "version": "0.1.1", "description": "Bare router for React components, using props as query string", "main": "src/main.js", - "scripts": { - "test": "mocha tests/" - }, "repository": { "type": "git", "url": "https://github.com/skidding/react-minimal-router.git" }, "devDependencies": { "chai": "^2.2.0", + "coveralls": "^2.11.2", + "istanbul": "^0.3.13", + "istanbul-instrumenter-loader": "^0.1.2", + "jscs": "^1.12.0", + "karma": "^0.12.31", + "karma-chai": "^0.1.0", + "karma-cli": "0.0.4", + "karma-coverage": "^0.2.7", + "karma-mocha": "^0.1.10", + "karma-mocha-reporter": "^1.0.2", + "karma-phantomjs-launcher": "^0.1.4", + "karma-sinon-chai": "^0.3.0", + "karma-webpack": "^1.5.0", "lodash": "^3.6.0", - "mocha": "^2.2.1", + "mocha": "^2.2.4", "sinon": "^1.14.1", - "sinon-chai": "^2.7.0" + "sinon-chai": "^2.7.0", + "webpack": "^1.8.2" }, "dependencies": { "react": "^0.13.1" + }, + "scripts": { + "pretest": "jscs ./", + "test": "karma start --single-run", + "coveralls": "cat tests/coverage/*/lcov.info | node_modules/coveralls/bin/coveralls.js" } } diff --git a/tests/bind-polyfill.js b/tests/bind-polyfill.js new file mode 100644 index 0000000..2f3f1e2 --- /dev/null +++ b/tests/bind-polyfill.js @@ -0,0 +1,36 @@ +/** + * PhantomJS doesn't support Function.prototype.bind natively, so + * polyfill it whenever this module is required. + */ + +(function() { +var Ap = Array.prototype; +var slice = Ap.slice; +var Fp = Function.prototype; + +if (!Fp.bind) { + Fp.bind = function(context) { + var func = this; + var args = slice.call(arguments, 1); + + function bound() { + var invokedAsConstructor = func.prototype && (this instanceof func); + return func.apply( + // Ignore the context parameter when invoking the bound function + // as a constructor. Note that this includes not only constructor + // invocations using the new keyword but also calls to base class + // constructors such as BaseClass.call(this, ...) or super(...). + !invokedAsConstructor && context || this, + args.concat(slice.call(arguments)) + ); + } + + // The bound function must share the .prototype of the unbound + // function so that any object created by one constructor will count + // as an instance of both constructors. + bound.prototype = func.prototype; + + return bound; + }; +} +})(); diff --git a/tests/router.js b/tests/router.js index b622bc5..60caf1d 100644 --- a/tests/router.js +++ b/tests/router.js @@ -1,25 +1,19 @@ var React = require('react'), _ = require('lodash'), - chai = require('chai'), - expect = chai.expect, - sinon = require('sinon'), - sinonChai = require('sinon-chai'), uri = require('../src/uri.js'), Router = require('../src/router.js'); -chai.use(sinonChai); - describe('Router class', function() { var ComponentClass = {}, componentInstance = {}, routerOptions, routerInstance, - location, + uriLocation, uriParams; var stubWindowApi = function() { sinon.stub(Router.prototype, '_getCurrentLocation', function() { - return location; + return uriLocation; }); sinon.stub(Router.prototype, '_isPushStateSupported').returns(true); sinon.stub(Router.prototype, '_bindPopStateEvent'); @@ -37,7 +31,7 @@ describe('Router class', function() { var genericTests = function() { it('should unserialize location', function() { - expect(uri.parseLocation.lastCall.args[0]).to.equal(location); + expect(uri.parseLocation.lastCall.args[0]).to.equal(uriLocation); }); it('should call getComponentClass with name', function() { @@ -101,7 +95,7 @@ describe('Router class', function() { // private methods that wrap those calls //expect(routerInstance._pushHistoryState).to.have.been.called; expect(routerInstance._pushHistoryState.lastCall.args[1]) - .to.equal(location); + .to.equal(uriLocation); }); }; @@ -118,7 +112,7 @@ describe('Router class', function() { }); // Fake browser location and mock (already tested) uri.js lib - location = 'mypage.com?component=List&dataUrl=users.json'; + uriLocation = 'mypage.com?component=List&dataUrl=users.json'; uriParams = { component: 'List', @@ -153,7 +147,7 @@ describe('Router class', function() { describe('changing location', function() { beforeEach(function() { - location = 'mypage.com?component=User&dataUrl=user.json'; + uriLocation = 'mypage.com?component=User&dataUrl=user.json'; uriParams = { component: 'User', @@ -163,7 +157,7 @@ describe('Router class', function() { describe('.goTo method', function() { beforeEach(function() { - routerInstance.goTo(location); + routerInstance.goTo(uriLocation); }); pushLocationTests(); @@ -175,7 +169,7 @@ describe('Router class', function() { routerInstance.routeLink({ preventDefault: function() {}, currentTarget: { - href: location + href: uriLocation } }); }); diff --git a/tests/uri.js b/tests/uri.js index 2ceb773..db17e07 100644 --- a/tests/uri.js +++ b/tests/uri.js @@ -1,11 +1,9 @@ -var chai = require('chai'), - expect = chai.expect, - uri = require('../src/uri.js'); +var uri = require('../src/uri.js'); describe('uri lib', function() { it('should parse stringified and encoded props from location', function() { - location = 'mypage.com?name=Jack&info=%7B%22age%22%3A25%7D'; - params = uri.parseLocation(location); + var uriLocation = 'mypage.com?name=Jack&info=%7B%22age%22%3A25%7D'; + params = uri.parseLocation(uriLocation); expect(params.name).to.equal('Jack'); expect(params.info.age).to.equal(25);