Skip to content

Commit

Permalink
Behave Node Client
Browse files Browse the repository at this point in the history
  • Loading branch information
gmccreadie committed Jun 26, 2015
1 parent 9873f8b commit c24819b
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
features
node_modules
102 changes: 101 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,101 @@
# behave-pro-node
# Behave Pro NodeJS Client

```
$ npm install behavepro -g
```

See [API Key setup](introduction.html) to retrieve the required credentials.

## Using from the command line

Parameters can either be passed from the command line:

```
$ behavepro [--id PROJECT ID] [--userId USER] [--apiKey KEY]
```

Available parameters:

* [**--host HOST**] *Behave Pro host - default: 'http://behave.pro'*
* [**--id PROJECT ID**] *JIRA project id*
* [**--userId USER**] *Behave Pro user id*
* [**--apiKey KEY**] *Behave Pro api key*
* [**--output DIRECTORY**] *Output directory - default: 'features'*
* [**--manual**] *Include scenarios marked as manual*
* [**--config CONFIG**] *JSON config file - relative to current directory*

If the three required parameters are missing, they will be attempted to be read from a json config file in the current directory:

```
$ behavepro
```

config.json
```
[{
"id": 10000,
"userId": "amlyYToyNDM0ZG.....ZiNzQwNGI=",
"apiKey": "44993b0481838e.....a246c723e8e"
}, {
"id": 10100,
"userId": "amlyYToyNDM0ZG.....ZiNzQwNGI=",
"apiKey": "b038a67e0f15e5.....fae00662c8a"
}]
```

Any additional parameters are to be specified from the command line.

The host can vary between products, see table below.

<table>
<tr>
<th>Product</th>
<th>Host</th>
</tr>

<tr>
<td>Behave Pro Cloud (default)</td>
<td>https://behave.pro</td>
</tr>

<tr>
<td>Behave Pro Server</td>
<td>Address of the VM</td>
</tr>

<tr>
<td>Behave for JIRA</td>
<td>JIRA address</td>
</tr>
</table>


## Using from within a script

You can use the client in your own scripts to download features from Behave Pro.

```
$ npm install behavepro --save
```


```
var BehavePro = require('behavepro');
BehavePro({
"id": 10000,
"userId": "amlyYToyNDM0ZG.....ZiNzQwNGI=",
"apiKey": "44993b0481838e.....a246c723e8e"
}, function() {
// done
});
```

Available parameters:

* **"host": HOST** - *Behave Pro host - default: 'http://behave.pro'*
* **"id": ID** - *JIRA project id*
* **"userId": USERID** - *Behave Pro user id*
* **"apiKey": APIKEY** - *Behave Pro api key*
* **"output": DIRECTORY** - *Output directory - default: 'features'*
* **"manual": true** - *Include scenarios marked as manual*
38 changes: 38 additions & 0 deletions bin/cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env node
'use strict'
var BehavePro = require('../lib/behavepro');
var args = require('minimist')(process.argv.slice(2));
var packageJson = require('../package.json');

if (args.help) {
console.log(
'Behave Pro NodeJS client v' + packageJson.version + '\n'+
'$ behavepro [--id PROJECT ID] [--userId USER] [--apiKey KEY]\n\n' +
'[--host HOST] Behave Pro host - default: \'http://behave.pro\'\n' +
'[--id PROJECT ID] JIRA project id\n' +
'[--userId USER] Behave Pro user id\n' +
'[--apiKey KEY] Behave Pro api key\n' +
'[--output DIRECTORY] Output directory - default: \'features\'\n' +
'[--manual] Include scenarios marked as manual\n' +
'[--config CONFIG] JSON config file - relative to current directory\n' +
'Further docs at http://docs.behave.pro'
);
return;
}

var settings = {
host: args.host || 'https://behave.pro',
id: args.key || args.project || args.id,
userId: args.user || args.userId,
apiKey: args.api || args.apiKey || args.password,
output: args.output || args.dir || args.directory || 'features',
manual: args.manual || args.m || false,
config: args.config || 'config.json'
};

// if these aren't defined, attempt to read them from config.json
if (settings.id && settings.userId && settings.apiKey) {
BehavePro.fetchFeatures(settings);
} else {
BehavePro.fetchFeaturesFromConfig(settings);
}
19 changes: 19 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env node
'use strict'
var BehavePro = require('./lib/behavepro');
var _ = require('underscore');

var defaultSettings = {
host: 'https://behave.pro',
output: 'features',
manual: false,
config: 'config.json'
};

module.exports = function(settings, callback) {
_.defaults(settings, defaultSettings);
BehavePro.fetchFeatures(settings, function() {
console.log(settings);
if (callback) callback();
});
}
115 changes: 115 additions & 0 deletions lib/behavepro.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#!/usr/bin/env node
'use strict'
var request = require('request');
var unzip = require('unzip2');
var fs = require('fs');
var mkdir = require('mkdirp');
var _ = require('underscore');

module.exports.fetchFeaturesFromConfig = function(settings, callback) {
fs.exists(process.cwd() + '/' + settings.config, function(exists) {
if (exists) {
var configuration = require(process.cwd() + '/' + settings.config);
configuration.forEach(function(config) {
_.extend(settings, config);
fetchFeatures(settings, callback);
});
} else {
var err = new Error('Could not find config at ' + process.cwd() + '/' + settings.config);
throw err;
}
});
}

var fetchFeatures = function(settings, callback) {
var url = settings.host + '/rest/cucumber/1.0/project/' + settings.id+ '/features?manual=' + settings.manual;
var path = settings.output + '/' + settings.id;

ensureSettingsExist(settings.id, settings.userId, settings.apiKey, function() {
console.log('Downloading features from JIRA project ' + settings.id + '...');
request({
url: url,
headers: {
Authorization: 'Basic ' + new Buffer(settings.userId + ':' + settings.apiKey).toString('base64')
},
encoding: null
}, function(error, response, body) {
if (error) throw error;
var err = null;
switch(response.statusCode) {
case 500:
err = new Error('Server error - Are you using the correct host?');
throw err;
return;
case 401:
err = new Error('Unauthorized - ensure keys are valid');
throw err;
return;
case 200:
break;
default:
err = new Error(response.statusCode + ' http error when downloading');
throw err;
return;
}

mkdir(path, function(err) {
if (err) throw err;
writeFeatures(body, path, function() {
countFeatures(path, function(files) {
console.log('Saved ' + files.length + ' ' + (files.length > 1 ? 'features' : 'feature') + ' to ' + process.cwd() + '/' + path + '/');
});
if (callback) callback();
});
});
});
});
}

module.exports.fetchFeatures = fetchFeatures;

function writeFeatures(body, path, callback) {
fs.writeFile(path + '.zip', body, function(err) {
if (err) throw err;
var stream = fs.createReadStream(path + '.zip').pipe(
unzip.Extract({
path: path
})
);

stream.on('close', function() {
removeZip(path + '.zip');
callback();
});
});
}

function ensureSettingsExist(id, userId, apiKey, callback) {
var err = null;
if (!id) {
err = new Error('Project id missing');
throw err;
}
if (!userId) {
err = new Error('User id missing');
throw err;
}
if (!apiKey) {
err = new Error('API key missing');
throw err;
}
if (callback) callback();
}

function countFeatures(path, callback) {
fs.readdir(path, function(err, files) {
callback(files);
});
}

function removeZip(file, callback) {
fs.unlink(file, function(err) {
if (err) throw err;
if (callback) callback();
});
}
21 changes: 21 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "behave-pro-js",
"version": "0.0.1",
"description": "Behave Pro JS exporter",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Hindsight Software Ltd",
"license": "MIT",
"dependencies": {
"minimist": "^1.1.1",
"mkdirp": "^0.5.1",
"request": "^2.58.0",
"underscore": "^1.8.3",
"unzip2": "^0.2.5"
},
"bin": {
"behavepro": "bin/cli.js"
}
}

0 comments on commit c24819b

Please sign in to comment.