Moxee
Enforcing modularity in AngularJS applications.

Here's the problem. Angular's module system is this big global context.
This makes it impossible for you to enforce any kind of modularity in Angular applications. And in a large application
with many developers, this becomes a serious issue very fast.
Moxee will create tests for you which will ensure that no injectable function is requiring anything that the module
doesn't provide on its own (or via one of its dependencies).
Supported Injectable Functions
- Auto-testing components to ensure they only utilize components that they should
invokeQueue (includes all injectable functions when creating angular-things, like services, directives, etc.)
- Directive controllers
- angular-ui-router state controllers
Injectable Functions to support
configQueue
runQueue
- Any
$injector.invoke call. ... good luck with this one...
- Use of directives in templates for states and directives... good luck with this one too...
- Am I missing any?
Moxee's goal is to enforce modularity in Angular applications so we can develop maintainable applications with
confidence that they wont be maintenance nightmares in the future. Moxee is part of a larger initiative which is still
a WIP. Look forward to what's coming :-)
Other TODOs
- Currently, we only support
mocha and chai. Would like to support any testing framework.
Examples
There's a very simple example application in the example directory which will hopefully be instructive. If
you open the index.html in a browser, you'll notice the application works just fine, no errors/warnings/etc. However,
if you run the tests, you'll notice that Moxee has created tests that fail because modules are using other module's
stuff even though they don't explicitly depend on them.
Usage
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['mocha', 'chai'],
files: [
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'node_modules/angular-ui-router/release/angular-ui-router.js',
'node_modules/moxee/dist/moxee.js',
'js/*.js',
'test/*.js'
],
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['PhantomJS'],
singleRun: false,
plugins: [
'karma-mocha',
'karma-chai',
'karma-phantomjs-launcher'
]
});
};
var mainModuleName = 'moxeeExampleParentModule';
var $injector = angular.bootstrap(document, [mainModuleName]);
var allStates = $injector.get('$state').get();
moxee.harness.stateControllers(allStates);
var myModulePrefix = 'moxeeExample';
moxee.harness.invokeQueue(mainModuleName, function shouldHarnessModule(ngModuleName) {
return ngModuleName.indexOf(myModulePrefix) === 0;
});
State Controllers
Right now, if you're going to use the stateControllers harnesser, you'll have to add two things for each of your
states data property:
$stateProvider.state({
data: {
ngModule: 'moxeeExampleStateModule',
parent: 'home'
}
});
The reason for this is because for moxee to know what a controller should have access to, it needs to know what
module to initialize for the tests (for the injector) and it also needs to know the parent's resolve properties so it
can mock those.
I think it should be possible to find the parent state of a given state, so hopefully I can get that working (or a PR
would be nice), but I don't think there's a way to get around the data.ngModule requirement. I recommend an
abstraction that would do this for you. I've got one right now in my own project, and I'm working on open sourcing it :)