Skip to content

Commit

Permalink
Autogenerate a test when generating an ability
Browse files Browse the repository at this point in the history
Fixes minutebase#11, Resolves minutebase#8, Resolves minutebase#13.
  • Loading branch information
blimmer committed Jul 3, 2015
1 parent cd0c733 commit 9dbadf9
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 12 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Master

## v0.6.0
* Generate unit tests when creating an ability

## v0.5.0

* Ember 1.13.x support
Expand Down Expand Up @@ -40,4 +43,4 @@

## v0.1.0

* Initial usable version
* Initial usable version
35 changes: 25 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ You want to conditionally allow creating a new blog post:
We define an ability for the `Post` resource in `/app/abilities/post.js`:

```javascript
import Ember from 'ember';
import { Ability } from 'ember-can';

export default Ability.extend({
canWrite: function() {
canWrite: Ember.computed('user.isAdmin', function() {
return this.get('user.isAdmin');
}.property('user.isAdmin')
})
});
```

Expand All @@ -53,10 +54,10 @@ export default Ember.Route.extend(CanMixin, {

## Installation

Install this addon via npm:
Install this addon via ember-cli:

```
npm install --save-dev ember-can
ember install ember-can
```

## Compatibility
Expand All @@ -65,7 +66,7 @@ npm install --save-dev ember-can
| ----------------- | --------------------- |
| 1.9.x | 0.2 |
| 1.10 through 1.12 | 0.4 |
| 1.13 and beyond | 0.5 |
| 1.13 and beyond | 0.5+ |

## Abilities

Expand All @@ -74,26 +75,27 @@ An ability class protects an individual model / resource which is available in t
The ability checks themselves are simply standard Ember objects with computed properties:

```javascript
import Ember from 'ember';
import { Ability } from 'ember-can';

export default Ability.extend({
// only admins can write a post
canWrite: function() {
canWrite: Ember.computed('user.isAdmin', function() {
return this.get('user.isAdmin');
}.property('user.isAdmin'),
}),

// only the person who wrote a post can edit it
canEdit: function() {
canEdit: Ember.computed('user.id', 'model.author', function() {
return this.get('user.id') === this.get('model.author');
}.property('user.id', 'model.author')
})
});
```

## Handlebars Helpers

The `can` helper is meant to be used with `{{if}}` and `{{unless}}` to protect a block.

The first parameter is a string which is used to find the ability class call the appropriate property (see "Looking up abilities" below).
The first parameter is a string which is used to find the ability class call the appropriate property (see [Looking up abilities](#looking-up-abilities)).

The second parameter is an optional model object which will be given to the ability to check permissions.

Expand Down Expand Up @@ -234,6 +236,19 @@ export default Ember.Controller.extend({
});
```

## Testing
Make sure that you've either `ember install`-ed this addon, or run the addon
blueprint via `ember g ember-can`. This is an important step that teaches the
test resolver how to resolve abilities from the file structure.

An ability unit test will be created each time you generate a new ability via
`ember g ability <name>`. The package currently supports generating QUnit and
Mocha style tests.

To unit test components that use the `can` helper, you'll need to `needs` the
ability and helper file like this:
``` needs: ['helper:can', 'ability:foo'] ```

## Development

### Installation
Expand Down
9 changes: 9 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ Whilst experimenting with the API & benefiting from changes in Ember, we've had

Here are the details on updating from previous versions.

## From v0.5.x
We now automatically generate an abilities test file when generating an ability.
This required a modification to the test resolver that runs when you `ember install`
this addon for the first time. When upgrading to v0.6.0+ you'll need to run the
addon's generator like this:
```
ember g ember-can
```

## From v0.4.x

Prior to v0.5 we supported defining injections in `/config/environment.js`, this has been removed in preference
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<%= imports %>

<%= test %>
69 changes: 69 additions & 0 deletions blueprints/ability-test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*jshint node:true*/
var EOL = require('os').EOL;

module.exports = {
description: 'Generates an ability unit test.',

_getTestStyle: function() {
if ('ember-cli-mocha' in this.project.addonPackages) {
return 'mocha';
} else if ('ember-cli-qunit' in this.project.addonPackages) {
return 'qunit';
}
},

locals: function(options) {
var name = options.entity.name;

var testStyle = this._getTestStyle();
if (!testStyle) {
this.ui.writeLine('Couldn\'t determine test style - using QUnit');
testStyle = 'qunit';
}

var imports, test;
if (testStyle === 'qunit') {
imports =
"import { moduleFor, test } from 'ember-qunit';";
test =
"moduleFor('ability:" + name + "', 'Unit | Ability | " + name + "', {" + EOL +
" // Specify the other units that are required for this test." + EOL +
" // needs: ['service:foo']" + EOL +
"});" + EOL + EOL +
"// Replace this with your real tests." + EOL +
"test('it exists', function(assert) {" + EOL +
" var ability = this.subject();" + EOL +
" assert.ok(ability);" + EOL +
"});";
} else if (testStyle === 'mocha') {
imports =
"/* jshint expr:true */" + EOL +
"import { expect } from 'chai';" + EOL +
"import {" + EOL +
" describeModule," + EOL +
" it" + EOL +
"} from 'ember-mocha';";
test =
"describeModule(" + EOL +
" 'ability:" + name + "'," + EOL +
" '" + name + " Ability'," + EOL +
" {" + EOL +
" // Specify the other units that are required for this test." + EOL +
" // needs: ['service:foo']" + EOL +
" }," + EOL +
" function() {" + EOL +
" // Replace this with your real tests." + EOL +
" it('exists', function() {" + EOL +
" var ability = this.subject();" + EOL +
" expect(ability).to.be.ok;" + EOL +
" });" + EOL +
" }" + EOL +
");";
}

return {
imports: imports,
test: test
};
}
};
19 changes: 19 additions & 0 deletions blueprints/ember-can/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*jshint node:true*/

var EOL = require('os').EOL;

module.exports = {
name: 'ember-can',

normalizeEntityName: function() {},

afterInstall: function() {
return this.insertIntoFile(
'tests/helpers/resolver.js',
"resolver.pluralizedTypes.ability = 'abilities';" + EOL,
{
before: "export default resolver"
}
);
}
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ember-can",
"version": "0.5.0",
"version": "0.6.0",
"description": "Simple authorisation addon for Ember apps",
"directories": {
"doc": "doc",
Expand Down

0 comments on commit 9dbadf9

Please sign in to comment.