Skip to content

Commit

Permalink
Modernize (#8)
Browse files Browse the repository at this point in the history
Fixes #7 

* Migrates tests to AVA
* Adopts ES2015 features
* Switches linting to ESLint
* Configures test coverage with Coveralls
* Adds badges to README
* Bumps node versions in .travis.yml
  • Loading branch information
ecowden committed Feb 4, 2017
1 parent 510f616 commit 6a377c1
Show file tree
Hide file tree
Showing 22 changed files with 211 additions and 236 deletions.
15 changes: 15 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"env": {
"node": true,
"es6": true
},
"extends": "standard",
"rules": {
"space-before-function-paren": ["error", {
"anonymous": "always",
"named": "never",
"asyncArrow": "always"
}]
},
"no-var": ["error"]
}
21 changes: 0 additions & 21 deletions .jshintrc

This file was deleted.

6 changes: 4 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
language: node_js
node_js:
- "0.12"
- "iojs"
- "4"
- "6"
after_success:
- './node_modules/.bin/nyc report --reporter=text-lcov | ./node_modules/.bin/coveralls'
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

Create a Pluto dependency injection module from files in a path or paths.

| Branch | Status |
| ------------- |:------------- |
| Master | [![Build Status](https://travis-ci.org/ecowden/pluto-path.png?branch=master)](https://travis-ci.org/ecowden/pluto-path) [![Coverage Status](https://coveralls.io/repos/github/ecowden/pluto-path/badge.svg?branch=master)](https://coveralls.io/github/ecowden/pluto-path?branch=master) |
| All | [![Build Status](https://travis-ci.org/ecowden/pluto-path.png)](https://travis-ci.org/ecowden/pluto-path) |

## Usage

### Simplified Options
Expand Down
4 changes: 2 additions & 2 deletions test/fixtures/dir1/a.js → lib/fixtures/dir1/a.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ module.exports = function aFactory(b) {
return {
name: 'a',
b: b
};
};
}
}
4 changes: 2 additions & 2 deletions test/fixtures/dir1/b.js → lib/fixtures/dir1/b.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = function bFactory() {
return {
name: 'b'
};
};
}
}
5 changes: 5 additions & 0 deletions lib/fixtures/dir2/MyConstructor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = function MyConstructor(myFactory, b) {
this.name = 'MyConstructor'
this.b = b
this.myFactory = myFactory
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ module.exports = function myFactory(myData) {
return {
name: 'myFactory',
myData: myData
};
};
}
}
52 changes: 25 additions & 27 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,41 @@
var requirePath = require('require-path');
var pluto = require('pluto');
var standardNamingStrategy = require('./standardNamingStrategy');
var standardBindingStrategy = require('./standardBindingStrategy');
var lodash = require('lodash');
'use strict'

const requirePath = require('require-path')
const pluto = require('pluto')
const standardNamingStrategy = require('./standardNamingStrategy')
const standardBindingStrategy = require('./standardBindingStrategy')
const lodash = require('lodash')

module.exports = function plutoPath(o) {
var options = buildOptions(o);
const options = buildOptions(o)

return requirePath(options)
.then(function(components) {

var plutoModule = pluto.createModule(function(bind) {
for (var filename in components) {
var component = components[filename];

var componentName = standardNamingStrategy(filename);
var bindingName = standardBindingStrategy(filename, component);
bind(componentName)[bindingName](component);
.then((components) => {
const plutoModule = pluto.createModule((bind) => {
for (let filename in components) {
const component = components[filename]

const componentName = standardNamingStrategy(filename)
const bindingName = standardBindingStrategy(filename, component)
bind(componentName)[bindingName](component)
}
if(options.extraBindings) {
options.extraBindings(bind);
if (options.extraBindings) {
options.extraBindings(bind)
}
})

});

return plutoModule;

});

};
return plutoModule
})
}

function buildOptions(o) {
if (typeof o === 'string' || lodash.isArray(o)) {
return {
path: o
};
}
} else if (lodash.isObject(o)) {
return o;
return o
} else {
throw new Error('options must be a string, array or strings or an object');
throw new Error('options must be a string, array or strings or an object')
}
}
70 changes: 70 additions & 0 deletions lib/indexSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'use strict'

const test = require('ava')
const path = require('path')

const plutoPath = require('./index')
const fixturesPath = path.join(__dirname, 'fixtures')
const simpleTestPath = path.join(fixturesPath, 'dir1')
const complexTextPath = path.join(fixturesPath, 'dir2')

function* simpleBindingMacro(t, input, expected) {
const app = yield plutoPath(simpleTestPath)
const a = app.get('a')
t.is(typeof a, 'object')
t.deepEqual(a.b, require('./fixtures/dir1/b')())
}

simpleBindingMacro.title = (providedTitle, input, expected) => `The main function accepts ${providedTitle}`.trim()

test('a single `path` string', simpleBindingMacro, simpleTestPath)
test('an array of `path` strings', simpleBindingMacro, [simpleTestPath])
test('a configuration object with a `path`', simpleBindingMacro, {
path: simpleTestPath
})

test('The main function accepts `extraBindings` property in the config object', function* (t) {
const app = yield plutoPath({
path: simpleTestPath,
extraBindings: function (bind) {
bind('theAnswer').toInstance(42)
}
})
t.is(app.get('theAnswer'), 42)
})

test('The main function throws a meaningful error if given a bad configuration type', function* (t) {
const error = t.throws(() => {
plutoPath(42)
}, Error)
t.is(error.message, 'options must be a string, array or strings or an object')
})

test('given complex filex, it binds a non-function object using `toInstance`', function* (t) {
const app = yield plutoPath(complexTextPath)
const actual = app.get('myData')
const expected = require('./fixtures/dir2/innerDir/myData.json')
t.is(actual, expected)
})

test('given complex filex, it binds a factory function using `toFactory`', function* (t) {
const app = yield plutoPath(complexTextPath)
const actual = app.get('myFactory')
const expected = require('./fixtures/dir2/myFactory')()
t.is(actual.name, expected.name)
})

test('given complex filex, it binds a constructor function using `toConstructor`', function* (t) {
const MyConstructor = require('./fixtures/dir2/MyConstructor')
const app = yield plutoPath([complexTextPath, simpleTestPath])
const actual = app.get('MyConstructor')
t.is(actual.name, MyConstructor.name)
t.truthy(actual instanceof MyConstructor)
})

test('given complex filex, it binds across modules', function* (t) {
const app = yield plutoPath([complexTextPath, simpleTestPath])
const actual = app.get('MyConstructor')
const expected = require('./fixtures/dir1/b')()
t.is(actual.b.name, expected.name)
})
14 changes: 8 additions & 6 deletions lib/standardBindingStrategy.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
var lodash = require('lodash');
'use strict'

var STARTS_WITH_CAPITAL = /^[A-Z]/;
const lodash = require('lodash')

const STARTS_WITH_CAPITAL = /^[A-Z]/

/**
* Standard strategy for choosing how a component should be bound in Pluto, returning
* the name of one of Pluto's binding functions.
*/
module.exports = function standardBindingStrategy(name, component) {
if (!lodash.isFunction(component)) {
return 'toInstance';
return 'toInstance'
}
if (name.match(STARTS_WITH_CAPITAL)) {
return 'toConstructor';
return 'toConstructor'
}
return 'toFactory';
};
return 'toFactory'
}
22 changes: 22 additions & 0 deletions lib/standardBindingStrategySpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict'

const test = require('ava')

var standardBindingSelector = require('./standardBindingStrategy')

test('a component that is not a function is bound with `toInstance`', function* (t) {
const actual = standardBindingSelector('myInstance', {})
t.is(actual, 'toInstance')
})

test('a lower-case function is bound with `toFactory`', function* (t) {
const actual = standardBindingSelector('myFactory', noop)
t.is(actual, 'toFactory')
})

test('a function with an upper-case name is bound with `toConstructor`', function* (t) {
const actual = standardBindingSelector('MyContructor', noop)
t.is(actual, 'toConstructor')
})

function noop() {}
12 changes: 7 additions & 5 deletions lib/standardNamingStrategy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
var path = require('path');
'use strict'

const path = require('path')

module.exports = function standardNamingStrategy(filename) {
/*
Expand All @@ -10,7 +12,7 @@ module.exports = function standardNamingStrategy(filename) {
* `snakeCase` to better fit with JavaScript naming conventions, but this is
* less critical since these are legal JavaScript variable names.
*/
var extension = path.extname(filename);
var basename = path.basename(filename, extension);
return basename;
};
const extension = path.extname(filename)
const basename = path.basename(filename, extension)
return basename
}
14 changes: 14 additions & 0 deletions lib/standardNamingStrategySpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict'

const test = require('ava')

const filenameToComponentName = require('./standardNamingStrategy')

test('standardNamingStrategy drops extensions', function* (t) {
const actual = filenameToComponentName('target.ext')
t.is(actual, 'target')
})
test('standardNamingStrategy drops preceding paths', function* (t) {
const actual = filenameToComponentName('path/target')
t.is(actual, 'target')
})
39 changes: 30 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,31 +1,52 @@
{
"name": "pluto-path",
"version": "0.3.0",
"version": "0.4.0",
"description": "Create a Pluto dependency injection module from files in a path or paths",
"main": "lib/index.js",
"scripts": {
"test": "mocha --recursive",
"autotest": "mocha --recursive -w"
"test": "nyc ava --verbose",
"autotest": "ava --verbose --watch",
"lint": "eslint .",
"lint-fix": "eslint . --fix"
},
"engines": {
"node": ">=0.12"
"node": ">=4.0.0"
},
"keywords": [
"pluto",
"dependency",
"injection",
"di"
"di",
"dependency injection",
"testing"
],
"author": "Evan Cowden <evan38109@gmail.com>",
"license": "MIT",
"ava": {
"timeout": "1m",
"files": [
"lib/**/*Spec.js",
"*Spec.js"
],
"babel": {
"presets": [
"es2015-node6"
]
}
},
"dependencies": {
"lodash": "^3.9.3",
"lodash": "^4.17.4",
"pluto": "^0.6.0",
"require-path": "^0.2.0"
},
"devDependencies": {
"chai": "^3.0.0",
"mocha": "^2.2.4",
"mocha-jshint": "^2.2.3"
"ava": "^0.18.0",
"babel-preset-es2015-node6": "^0.4.0",
"coveralls": "^2.11.15",
"eslint": "^3.14.1",
"eslint-config-standard": "^6.2.1",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^2.0.1",
"nyc": "^10.1.2"
}
}
5 changes: 0 additions & 5 deletions test/fixtures/dir2/MyConstructor.js

This file was deleted.

0 comments on commit 6a377c1

Please sign in to comment.