grunt-cucumberjs
Advanced tools
Comparing version 0.2.1 to 0.3.0
{ | ||
"name": "grunt-cucumberjs", | ||
"description": "Generates documentation from Cucumber features", | ||
"version": "0.2.1", | ||
"version": "0.3.0", | ||
"homepage": "https://github.com/mavdi/grunt-cucumberjs", | ||
@@ -6,0 +6,0 @@ "author": { |
# grunt-cucumberjs | ||
> Generates documentation from Cucumber features | ||
> Runs cucumberjs features and output results in various formats including html. | ||
@@ -28,10 +28,27 @@ ## Getting Started | ||
cucumberjs: { | ||
options: { | ||
format: 'html', | ||
output: 'my_report.html', | ||
theme: 'bootstrap' | ||
}, | ||
my_features: ['features/feature1.feature', 'features/feature2.feature'], | ||
other_features: { | ||
options: { | ||
output: 'output.html' | ||
output: 'other_report.html' | ||
}, | ||
format: 'html' | ||
}, | ||
}) | ||
src: ['other_features/feature1.feature', 'other_features/feature2.feature'] | ||
} | ||
} | ||
}); | ||
``` | ||
### Usage | ||
```bash | ||
#runs all features specified in task | ||
$ grunt cucumberjs | ||
#run specific features | ||
$ grunt cucumberjs --features=features/myFeature.feature | ||
``` | ||
### Options | ||
@@ -41,3 +58,3 @@ | ||
Type: `String` | ||
Default value: `''` | ||
Default: `''` | ||
@@ -48,36 +65,31 @@ passes the value as ```--steps``` parameter to cucumber. | ||
Type: `String` | ||
Default value: `''` | ||
Default: `''` | ||
passes the value as ```--tags``` parameter to cucumber. | ||
#### options.css | ||
#### options.theme | ||
Type: `String` | ||
Default value: `''` | ||
Default: `'foundation'` | ||
Available: `['foundation', 'bootstrap', 'simple']` | ||
Location of the CSS styles to be used by the html report wrapper. See ```templates/``` for details. | ||
Specifies which theme to use for the html report | ||
#### options.indexTemplate | ||
#### options.templateDir | ||
Type: `String` | ||
Default value: `''` | ||
Default: `'features/templates'` | ||
Location of html report wrapper. See ```templates/``` for details. | ||
Location of your custom templates. Simply name the template the same as the one you are trying to override and | ||
grunt-cucumberjs will use it over the default template | ||
#### options.featuresTemplate | ||
Type: `String` | ||
Default value: `''` | ||
Location of the html temoplate to be used when running each test. See ```templates/``` for details. | ||
#### options.output | ||
Type: `String` | ||
Default value: `''` | ||
Default: `'features_report.html'` | ||
Output file for the task. Please also include the appripriate extension. For example use ```js``` for ```json``` format. | ||
Report output location. Please also include the appropriate extension. For example use ```js``` for ```json``` format. | ||
#### format | ||
#### options.format | ||
Type: `String` | ||
Default value: `''` | ||
Default: `'html'` | ||
Available: `['pretty', 'progress', 'json', 'summary', 'html']` | ||
output format for the tests. The options are ```pretty```, ```progress```, ```json```, ```summary``` and ```html```. | ||
```html``` will output a pretty report of your tests. You can use your own templates with this. | ||
The output format for the tests. |
@@ -9,4 +9,2 @@ /* | ||
/*jshint curly: false */ | ||
'use strict'; | ||
@@ -17,36 +15,47 @@ | ||
var version = grunt.file.readJSON('./package.json').version; | ||
var projectPkg = grunt.file.readJSON('package.json'); | ||
var spawn = require('child_process').spawn; | ||
var _ = require('underscore'); | ||
grunt.registerTask('cucumberjs', 'Generates documentation from Cucumber features', function() { | ||
console.log('start'); | ||
grunt.registerMultiTask('cucumberjs', 'Run cucumber.js features', function() { | ||
var done = this.async(); | ||
var fileTypes = { | ||
html : 'html', | ||
json : 'js' | ||
}; | ||
var options = this.options({ | ||
outputPath: './', | ||
output: 'features_report.html', | ||
format: 'html', | ||
css: 'node_modules/grunt-cucumberjs/templates/foundation/styles.css', | ||
javascript: 'node_modules/grunt-cucumberjs/templates/foundation/script.js', | ||
moment: 'node_modules/grunt-cucumberjs/templates/foundation/moment.min.js', | ||
indexTemplate : 'node_modules/grunt-cucumberjs/templates/foundation/index.tmpl', | ||
featuresTemplate : 'node_modules/grunt-cucumberjs/templates/foundation/features.tmpl', | ||
buildTemplate : 'node_modules/grunt-cucumberjs/templates/foundation/build.tmpl' | ||
theme: 'foundation', | ||
templateDir: 'features/templates' | ||
}); | ||
var config = grunt.config.get('cucumberjs'); | ||
var spawn = require('child_process').spawn; | ||
var _ = require('underscore'); | ||
var commands = []; | ||
if(options.steps) commands.push('-r', options.steps); | ||
if(options.tags) commands.push('-t', options.tags); | ||
if(config.format && config.format !== 'html') { | ||
commands.push('-f', config.format); | ||
} else if(config.format === 'html') { | ||
if (options.steps) { | ||
commands.push('-r', options.steps); | ||
} | ||
if (options.tags) { | ||
commands.push('-t', options.tags); | ||
} | ||
if (options.format === 'html') { | ||
commands.push('-f', 'json'); | ||
} else { | ||
commands.push('-f', options.format); | ||
} | ||
if (grunt.option('features')) { | ||
commands.push(grunt.option('features')); | ||
} else { | ||
this.files.forEach(function(f) { | ||
f.src.forEach(function(filepath) { | ||
if (!grunt.file.exists(filepath)) { | ||
grunt.log.warn('Source file "' + filepath + '" not found.'); | ||
return; | ||
} | ||
commands.push(filepath); | ||
}); | ||
}); | ||
} | ||
var buffer = []; | ||
@@ -56,3 +65,7 @@ var cucumber = spawn('./node_modules/.bin/cucumber-js', commands); | ||
cucumber.stdout.on('data', function(data) { | ||
buffer.push(data); | ||
if (options.format === 'html') { | ||
buffer.push(data); | ||
} else { | ||
grunt.log.write(data); | ||
} | ||
}); | ||
@@ -66,42 +79,122 @@ | ||
cucumber.on('close', function (code) { | ||
var stdout = Buffer.concat(buffer); | ||
if(code != 0) { | ||
if (options.format === 'html') { | ||
var featureJsonOutput; | ||
var output = Buffer.concat(buffer).toString(); | ||
var featureStartIndex = output.substring(0, output.indexOf('"keyword": "Feature"')).lastIndexOf('['); | ||
var logOutput = output.substring(0, featureStartIndex - 1); | ||
var featureOutput = output.substring(featureStartIndex); | ||
try { | ||
featureJsonOutput = JSON.parse(featureOutput); | ||
} catch (e) { | ||
grunt.log.error('Unable to parse cucumberjs output into json.'); | ||
return done(false); | ||
} | ||
generateReport(featureJsonOutput, logOutput); | ||
} | ||
if (code !== 0) { | ||
grunt.log.error('failed tests, please see the output'); | ||
(config.format === 'html') ? publish(JSON.parse(stdout)) : grunt.log.write(stdout); | ||
return done(false); | ||
} else { | ||
return done(); | ||
} | ||
publish(JSON.parse(stdout)); | ||
return done(); | ||
}); | ||
var publish = function(features) { | ||
var renderedFeatures = renderFeatures(features); | ||
var renderedBuild = renderBuild({ | ||
version: version, | ||
time: new Date() | ||
/** | ||
* Adds passed/failed properties on features/scenarios | ||
* | ||
* @param {object} suite The test suite object | ||
*/ | ||
var setStats = function(suite) { | ||
var features = suite.features; | ||
features.forEach(function(feature) { | ||
feature.passed = 0; | ||
feature.failed = 0; | ||
if(!feature.elements) return; | ||
feature.elements.forEach(function(element) { | ||
element.passed = 0; | ||
element.failed = 0; | ||
element.notdefined = 0; | ||
element.skipped = 0; | ||
element.steps.forEach(function(step) { | ||
if(step.result.status === 'passed') return element.passed++; | ||
if(step.result.status === 'failed') return element.failed++; | ||
if(step.result.status === 'undefined') return element.notdefined++; | ||
element.skipped ++; | ||
}); | ||
if(element.failed > 0) return feature.failed++; | ||
feature.passed++; | ||
}); | ||
if(feature.failed > 0) return suite.failed++; | ||
suite.passed++; | ||
}); | ||
var wrapped = wrap(renderedFeatures, renderedBuild); | ||
grunt.file.write(options.outputPath + '/report.' + options.format, wrapped); | ||
}; | ||
suite.features = features; | ||
var renderFeatures = function(features) { | ||
var source = grunt.file.read(options.featuresTemplate); | ||
return _.template(source)({features : features, _ : _ }); | ||
return suite; | ||
}; | ||
var renderBuild = function(build) { | ||
var source = grunt.file.read(options.buildTemplate); | ||
return _.template(source)({build : build }); | ||
/** | ||
* Returns the path of a template | ||
* | ||
* @param {string} name The template name | ||
*/ | ||
var getPath = function(name) { | ||
var path = 'node_modules/grunt-cucumberjs/templates/' + options.theme + '/' + name; | ||
// return the users custom template if it has been defined | ||
if (grunt.file.exists(options.templateDir + '/' + name)) { | ||
path = options.templateDir + '/' + name; | ||
} | ||
return path; | ||
}; | ||
var wrap = function(renderedFeatures, renderedBuild) { | ||
var source = grunt.file.read(options.indexTemplate); | ||
var styles = grunt.file.read(options.css); | ||
var script = grunt.file.read(options.javascript) + grunt.file.read(options.moment); | ||
return _.template(source)({features : renderedFeatures, build: renderedBuild, styles : styles, script: script}); | ||
/** | ||
* Generate html report | ||
* | ||
* @param {object} featureOutput Features result object | ||
* @param {string} logOutput Contains any console statements captured during the test run | ||
*/ | ||
var generateReport = function(featureOutput, logOutput) { | ||
var suite = { | ||
name: projectPkg.name, | ||
features: featureOutput, | ||
passed: 0, | ||
failed: 0, | ||
logOutput: logOutput | ||
}; | ||
suite = setStats(suite); | ||
grunt.file.write( | ||
options.output, | ||
_.template(grunt.file.read(getPath('index.tmpl')))({ | ||
suite: suite, | ||
version: version, | ||
time: new Date(), | ||
features: _.template(grunt.file.read(getPath('features.tmpl')))({suite : suite, _ : _ }), | ||
styles: grunt.file.read(getPath('style.css')), | ||
script: grunt.file.read(getPath('script.js')) | ||
}) | ||
); | ||
grunt.log.writeln('Generated ' + options.output + ' successfully.'); | ||
}; | ||
}); | ||
}; | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
22
1
93
0
203708
377
2