Skip to content

Commit

Permalink
Merge pull request #2 from anilanar/tentacle-v0.1
Browse files Browse the repository at this point in the history
Fix small bugs, integrate gulp, mocha, browserify, karma.
  • Loading branch information
anilanar committed Oct 17, 2015
2 parents e756899 + e5a6fb1 commit d5449e3
Show file tree
Hide file tree
Showing 30 changed files with 14,692 additions and 55 deletions.
11 changes: 11 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
language: node_js
node_js:
- "stable"
before_script:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- npm install -g gulp
- npm install
script: npm run-script ci
addons:
firefox: "latest"
285 changes: 283 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,283 @@
# tentacle.mock
Auto-mock dependencies for angular tests
[![Build Status](https://travis-ci.org/anilanar/tentacle.js.svg?branch=master)](https://travis-ci.org/anilanar/tentacle.js)
[![Coverage Status](https://coveralls.io/repos/anilanar/tentacle.js/badge.svg?branch=master&service=github)](https://coveralls.io/github/anilanar/tentacle.js?branch=master)
[![npm version](https://badge.fury.io/js/tentacle.js.svg)](https://badge.fury.io/js/tentacle.js)

This utility library is unstable and experimental. You don't have to use it for all of your test suites. Give it a try for testing one of your services/controllers/directives!


# tentacle.js
---------------
Auto-mock dependencies for angular.js tests. See integration tests for examples.

Injecting or mocking dependencies is supported for services/factories, controllers and directives.

Filters and providers currently are not supported. However services returned by providers can be tested using tentacle.js.


### Table of Contents
1. [Installation](#1-installation)
2. [First steps](#2-first-steps)
3. [API and examples](#3-api-and-examples)
- [`tentacle.injectAll`](#tentacleinjectAll)
- [`tentacle.service`](#tentacleservice)
- [`tentacle.factory`](#tentaclefactory)
- [`tentacle.controller`](#tentaclecontroller)
- [`tentacle.controller.run`](#tentaclecontrollerrun)
- [`tentacle.directive`](#tentacledirective)
- [`tentacle.directive.run`](#tentacledirectiverun)
- [`tentacle.reset`](#tentaclereset)
4. [Advanced](#4-advanced)
- [How it works](#how-it-works)
- [`tentacle.globalInjects`](#tentacleglobalinjects)
- [`tentacle.mockExceptions`](#tentaclemockexceptions)

### 1. Installation

##### npm:
```
npm install tentacle.js
```
##### bower:
```
bower install tentacle.js
```

### 2. First steps

##### node.js:
```js
var tentacleInit = require('tentacle');
var angular = require('angular');
var globalScope = {}; // you can use global too,
// similar to window object
// in browsers
tentacleInit(global, angular)

// You can use globalScope.tentacle

describe('test', function () {
it('should have tentacle', function () {
expect(globalScope.tentacle).to.be.an.object;
// if you use 'global' object:
// expect(tentacle).to.be.an.object;
});
});
```

##### browsers (karma):

Add [dist/tentacle.js](dist/tentacle.js) to your files list in karma config. `tentacle` object is put into `window` global variable:

```js
describe('test', function () {
it('should have tentacle', function () {
expect(tentacle).to.be.an.object;
});
});
```

### 3. API and examples:

---
#### `tentacle.injectAll`
Injects all dependencies given a module name and a service, factory, controller or directive name.

###### Arguments

| Param | Type | Details
| ---------- | ------- | ----------
| moduleName | string | name of angular module
| name | string | name of service/factory/ctrl/directive

---

#### `tentacle.service`
#### `tentacle.factory`
Mocks all dependencies of an angular service, except those defined in `tentacle.mockExceptions`.

###### Usage
```js
// a simple service
angular.module('myModule').factory('myService', [
'anotherService',
function (anotherService) {
return {
myMethod: function () {
anotherService.anotherMethod();
};
}
}]);

// ----------------

// test
var mocks = tentacle.service('myModule', 'myService');
mocks.anotherService.anotherMethod = function () {
return 'HELLO';
};
expect(myService.myMethod()).to.equal('HELLO');
```

###### Arguments

| Param | Type | Details
| ----------- | ------- | ----------
| moduleName | string | name of angular module
| serviceName | string | name of service
| customMocks | object | _(optional)_ string-value pairs for overriding default mock object. defaults to an empty object
| defaultMock | any | _(optional)_ value to inject for mocked dependencies. provided values are deeply cloned before each injection. defaults to an empty object

###### Returns
`object{string: any}` : string-value pairs of mocked dependency names and their values

---

#### `tentacle.controller`
Mocks all dependencies of an angular controller, except those defined in `tentacle.mockExceptions`.

###### Usage
```js
// a simple controller
angular.module('myModule').controller('myCtrl', [
'$scope',
'anotherService',
function ($scope, anotherService) {
this.myMethod = function () {
anotherService.anotherMethod();
}
$scope.myValue = this.myMethod();
}]);

// ----------------

// test
var mocks = tentacle.controller('myModule', 'myCtrl');
mocks.anotherService.anotherMethod = function () {
return 'HELLO';
};
var ctrl = tentacle.controller.run();
expect(ctrl.myMethod()).to.equal('HELLO');
expect($scope.myValue).to.equal('HELLO');
```

###### Arguments

| Param | Type | Details
| ----------- | ------- | ----------
| moduleName | string | name of angular module
| ctrlName | string | name of controller
| customMocks | object | _(optional)_ string-value pairs for overriding default mock object. defaults to an empty object
| defaultMock | any | _(optional)_ value to inject for mocked dependencies. provided values are deeply cloned before each injection. defaults to an empty object

###### Returns
`object{string: any}` : string-value pairs of mocked dependency names and their values

---

#### `tentacle.controller.run`
Executes the last controller that was initialized using `tentacle.controller`.

###### Returns
`object : instance of controller

---

#### `tentacle.directive`
Mocks all dependencies of an angular controller, except those defined in `tentacle.mockExceptions`.

###### Usage
```js
// a simple directive
angular.module('myModule').directive('myDir', [
'anotherService',
function (anotherService) {
function link ($scope) {
$scope.myValue = anotherService.anotherMethod();
}
return {
restrict: 'EA',
scope: {
'myParam': '='
},
template: '<p>{{myParam}}</p>'
}
}]);

// ----------------

// test
var mocks = tentacle.directive('myModule', 'myDir');
mocks.anotherService.anotherMethod = function () {
return 'HELLO';
};
var elem = tentacle.directive.run('<my-dir my-param="param"></my-dir');
expect(isolateScope.myValue).to.equal('HELLO');
$scope.param = 'tentacle.js';
$scope.$digest();
var isolateScope = elem.isolateScope();
expect(isolateScope.myParam).to.equal('tentacle.js');
```

###### Arguments

| Param | Type | Details
| ----------- | ------- | ----------
| moduleName | string | name of angular module
| dirName | string | name of directive
| customMocks | object | _(optional)_ string-value pairs for overriding default mock object. defaults to an empty object
| defaultMock | any | _(optional)_ value to inject for mocked dependencies. provided values are deeply cloned before each injection. defaults to an empty object

###### Returns
`object{string: any}` : string-value pairs of mocked dependency names and their values

---

#### `tentacle.directive.run`
Executes the last controller that was initialized using `tentacle.controller`.

| Param | Type | Details
| ------- | ------- | ----------
| html | string | html to use for initializing directive. it must have an element that resolves to tested directive at **root**

###### Returns
`object` : an instance of [`angular.element`](https://docs.angularjs.org/api/ng/function/angular.element). the following methods are especially important for testing:
- `scope()`: returns scope
- `isolateScope()`: returns isolate scope if directive is defined to have one
- `controller('directiveName')`: returns controller that was set in directive definition using `controller` property.

---

### 4. Advanced
You can read the following for more advanced information on _tentacle.js_.

#### How it works
When dependencies are injected or mocked using _tentacle.js_, dependencies for given service, controller or directive are searched in `angular._invokeQueue`, a private/undocumented property of _angular_.

Dependencies in `tentacle.globalInjects` are always injected in the global scope while dependencies in `tentacle.mockExceptions` are never mocked.

#### `tentacle.globalInjects`
You can push more dependencies into this array. It is defined as follows:

```js
tentacle.globalInjects = [
'$rootScope',
'$q',
'$httpBackend',
'$templateCache',
'$compile'
];
```

#### `tentacle.mockExceptions`
You can push more dependencies into this array. It is defined as follows:

```js
tentacle.mockExceptions = [
'$http',
'$httpBackend',
'$rootScope',
'$q',
'$scope',
'$filter'
];
```
1 change: 1 addition & 0 deletions coverage/coverage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"/Users/anilanar/Projects/tentacle.js/src/index.js":{"path":"/Users/anilanar/Projects/tentacle.js/src/index.js","s":{"1":1,"2":1,"3":1,"4":30,"5":30,"6":30,"7":30,"8":30,"9":30,"10":30,"11":30,"12":30,"13":30,"14":30,"15":30,"16":30,"17":30,"18":30,"19":1,"20":13,"21":13,"22":13,"23":13,"24":1,"25":30,"26":1,"27":6,"28":6,"29":6,"30":6,"31":6,"32":1,"33":11,"34":11,"35":11,"36":11,"37":11,"38":11,"39":11,"40":5,"41":5,"42":5,"43":11,"44":1,"45":10,"46":10,"47":10,"48":10,"49":10,"50":5,"51":5,"52":5,"53":10,"54":1,"55":3,"56":3,"57":3,"58":3,"59":1,"60":2,"61":1,"62":2,"63":1,"64":294,"65":294,"66":1,"67":1,"68":21,"69":1,"70":213,"71":213,"72":1,"73":24,"74":24,"75":24,"76":24,"77":48,"78":48,"79":1,"80":30,"81":30,"82":44,"83":1,"84":26,"85":26},"b":{"1":[1,1],"2":[24,24],"3":[48,48]},"f":{"1":30,"2":13,"3":30,"4":6,"5":11,"6":5,"7":10,"8":5,"9":3,"10":2,"11":294,"12":1,"13":21,"14":213,"15":213,"16":24,"17":48,"18":30,"19":44,"20":26,"21":26},"fnMap":{"1":{"name":"init","line":6,"loc":{"start":{"line":6,"column":0},"end":{"line":6,"column":31}}},"2":{"name":"mock","line":37,"loc":{"start":{"line":37,"column":2},"end":{"line":37,"column":53}}},"3":{"name":"injectGlobals","line":44,"loc":{"start":{"line":44,"column":2},"end":{"line":44,"column":27}}},"4":{"name":"injectAll","line":48,"loc":{"start":{"line":48,"column":2},"end":{"line":48,"column":35}}},"5":{"name":"controller","line":56,"loc":{"start":{"line":56,"column":2},"end":{"line":56,"column":59}}},"6":{"name":"(anonymous_6)","line":65,"loc":{"start":{"line":65,"column":37},"end":{"line":65,"column":49}}},"7":{"name":"directive","line":73,"loc":{"start":{"line":73,"column":2},"end":{"line":73,"column":58}}},"8":{"name":"(anonymous_8)","line":80,"loc":{"start":{"line":80,"column":36},"end":{"line":80,"column":55}}},"9":{"name":"service","line":88,"loc":{"start":{"line":88,"column":2},"end":{"line":88,"column":56}}},"10":{"name":"async","line":95,"loc":{"start":{"line":95,"column":2},"end":{"line":95,"column":20}}},"11":{"name":"addToWindow","line":102,"loc":{"start":{"line":102,"column":2},"end":{"line":102,"column":44}}},"12":{"name":"reset","line":107,"loc":{"start":{"line":107,"column":2},"end":{"line":107,"column":19}}},"13":{"name":"(anonymous_13)","line":108,"loc":{"start":{"line":108,"column":31},"end":{"line":108,"column":47}}},"14":{"name":"injectDependency","line":113,"loc":{"start":{"line":113,"column":2},"end":{"line":113,"column":40}}},"15":{"name":"(anonymous_15)","line":114,"loc":{"start":{"line":114,"column":37},"end":{"line":114,"column":61}}},"16":{"name":"createMocksObject","line":119,"loc":{"start":{"line":119,"column":2},"end":{"line":119,"column":66}}},"17":{"name":"(anonymous_17)","line":125,"loc":{"start":{"line":125,"column":14},"end":{"line":125,"column":49}}},"18":{"name":"getDependencies","line":133,"loc":{"start":{"line":133,"column":2},"end":{"line":133,"column":41}}},"19":{"name":"(anonymous_19)","line":138,"loc":{"start":{"line":138,"column":12},"end":{"line":138,"column":30}}},"20":{"name":"provideValue","line":144,"loc":{"start":{"line":144,"column":2},"end":{"line":144,"column":42}}},"21":{"name":"(anonymous_21)","line":145,"loc":{"start":{"line":145,"column":24},"end":{"line":145,"column":44}}}},"statementMap":{"1":{"start":{"line":3,"column":0},"end":{"line":3,"column":26}},"2":{"start":{"line":4,"column":0},"end":{"line":4,"column":22}},"3":{"start":{"line":6,"column":0},"end":{"line":149,"column":1}},"4":{"start":{"line":7,"column":2},"end":{"line":7,"column":27}},"5":{"start":{"line":8,"column":2},"end":{"line":15,"column":4}},"6":{"start":{"line":16,"column":2},"end":{"line":22,"column":4}},"7":{"start":{"line":24,"column":2},"end":{"line":24,"column":30}},"8":{"start":{"line":25,"column":2},"end":{"line":25,"column":30}},"9":{"start":{"line":26,"column":2},"end":{"line":26,"column":30}},"10":{"start":{"line":27,"column":2},"end":{"line":27,"column":48}},"11":{"start":{"line":28,"column":2},"end":{"line":28,"column":50}},"12":{"start":{"line":29,"column":2},"end":{"line":29,"column":48}},"13":{"start":{"line":30,"column":2},"end":{"line":30,"column":40}},"14":{"start":{"line":31,"column":2},"end":{"line":31,"column":42}},"15":{"start":{"line":32,"column":2},"end":{"line":32,"column":40}},"16":{"start":{"line":33,"column":2},"end":{"line":33,"column":36}},"17":{"start":{"line":34,"column":2},"end":{"line":34,"column":36}},"18":{"start":{"line":35,"column":2},"end":{"line":35,"column":32}},"19":{"start":{"line":37,"column":2},"end":{"line":42,"column":3}},"20":{"start":{"line":38,"column":4},"end":{"line":38,"column":32}},"21":{"start":{"line":39,"column":4},"end":{"line":39,"column":77}},"22":{"start":{"line":40,"column":4},"end":{"line":40,"column":41}},"23":{"start":{"line":41,"column":4},"end":{"line":41,"column":23}},"24":{"start":{"line":44,"column":2},"end":{"line":46,"column":3}},"25":{"start":{"line":45,"column":4},"end":{"line":45,"column":47}},"26":{"start":{"line":48,"column":2},"end":{"line":54,"column":3}},"27":{"start":{"line":49,"column":4},"end":{"line":49,"column":36}},"28":{"start":{"line":50,"column":4},"end":{"line":50,"column":45}},"29":{"start":{"line":51,"column":4},"end":{"line":51,"column":55}},"30":{"start":{"line":52,"column":4},"end":{"line":52,"column":49}},"31":{"start":{"line":53,"column":4},"end":{"line":53,"column":27}},"32":{"start":{"line":56,"column":2},"end":{"line":71,"column":3}},"33":{"start":{"line":57,"column":4},"end":{"line":57,"column":32}},"34":{"start":{"line":58,"column":4},"end":{"line":58,"column":36}},"35":{"start":{"line":59,"column":4},"end":{"line":59,"column":36}},"36":{"start":{"line":60,"column":4},"end":{"line":60,"column":77}},"37":{"start":{"line":61,"column":4},"end":{"line":61,"column":52}},"38":{"start":{"line":62,"column":4},"end":{"line":64,"column":7}},"39":{"start":{"line":65,"column":4},"end":{"line":69,"column":6}},"40":{"start":{"line":66,"column":6},"end":{"line":66,"column":55}},"41":{"start":{"line":67,"column":6},"end":{"line":67,"column":30}},"42":{"start":{"line":68,"column":6},"end":{"line":68,"column":18}},"43":{"start":{"line":70,"column":4},"end":{"line":70,"column":23}},"44":{"start":{"line":73,"column":2},"end":{"line":86,"column":3}},"45":{"start":{"line":74,"column":4},"end":{"line":74,"column":80}},"46":{"start":{"line":75,"column":4},"end":{"line":75,"column":36}},"47":{"start":{"line":76,"column":4},"end":{"line":76,"column":52}},"48":{"start":{"line":77,"column":4},"end":{"line":79,"column":7}},"49":{"start":{"line":80,"column":4},"end":{"line":84,"column":6}},"50":{"start":{"line":81,"column":6},"end":{"line":81,"column":56}},"51":{"start":{"line":82,"column":6},"end":{"line":82,"column":30}},"52":{"start":{"line":83,"column":6},"end":{"line":83,"column":21}},"53":{"start":{"line":85,"column":4},"end":{"line":85,"column":23}},"54":{"start":{"line":88,"column":2},"end":{"line":93,"column":3}},"55":{"start":{"line":89,"column":4},"end":{"line":89,"column":80}},"56":{"start":{"line":90,"column":4},"end":{"line":90,"column":36}},"57":{"start":{"line":91,"column":4},"end":{"line":91,"column":27}},"58":{"start":{"line":92,"column":4},"end":{"line":92,"column":23}},"59":{"start":{"line":95,"column":2},"end":{"line":100,"column":3}},"60":{"start":{"line":96,"column":4},"end":{"line":98,"column":5}},"61":{"start":{"line":97,"column":6},"end":{"line":97,"column":29}},"62":{"start":{"line":99,"column":4},"end":{"line":99,"column":29}},"63":{"start":{"line":102,"column":2},"end":{"line":105,"column":3}},"64":{"start":{"line":103,"column":4},"end":{"line":103,"column":33}},"65":{"start":{"line":104,"column":4},"end":{"line":104,"column":39}},"66":{"start":{"line":107,"column":2},"end":{"line":111,"column":3}},"67":{"start":{"line":108,"column":4},"end":{"line":110,"column":7}},"68":{"start":{"line":109,"column":6},"end":{"line":109,"column":26}},"69":{"start":{"line":113,"column":2},"end":{"line":117,"column":3}},"70":{"start":{"line":114,"column":4},"end":{"line":116,"column":8}},"71":{"start":{"line":115,"column":6},"end":{"line":115,"column":44}},"72":{"start":{"line":119,"column":2},"end":{"line":131,"column":3}},"73":{"start":{"line":120,"column":4},"end":{"line":120,"column":30}},"74":{"start":{"line":122,"column":4},"end":{"line":122,"column":53}},"75":{"start":{"line":123,"column":4},"end":{"line":123,"column":62}},"76":{"start":{"line":124,"column":4},"end":{"line":130,"column":15}},"77":{"start":{"line":126,"column":8},"end":{"line":126,"column":52}},"78":{"start":{"line":127,"column":8},"end":{"line":127,"column":27}},"79":{"start":{"line":133,"column":2},"end":{"line":142,"column":3}},"80":{"start":{"line":135,"column":4},"end":{"line":135,"column":58}},"81":{"start":{"line":136,"column":4},"end":{"line":141,"column":32}},"82":{"start":{"line":139,"column":8},"end":{"line":139,"column":42}},"83":{"start":{"line":144,"column":2},"end":{"line":148,"column":3}},"84":{"start":{"line":145,"column":4},"end":{"line":147,"column":7}},"85":{"start":{"line":146,"column":6},"end":{"line":146,"column":39}}},"branchMap":{"1":{"line":96,"type":"if","locations":[{"start":{"line":96,"column":4},"end":{"line":96,"column":4}},{"start":{"line":96,"column":4},"end":{"line":96,"column":4}}]},"2":{"line":120,"type":"binary-expr","locations":[{"start":{"line":120,"column":15},"end":{"line":120,"column":23}},{"start":{"line":120,"column":27},"end":{"line":120,"column":29}}]},"3":{"line":126,"type":"binary-expr","locations":[{"start":{"line":126,"column":34},"end":{"line":126,"column":45}},{"start":{"line":126,"column":49},"end":{"line":126,"column":51}}]}}}}

0 comments on commit d5449e3

Please sign in to comment.