Skip to content

Commit

Permalink
Merge ff0ecd5 into 235d169
Browse files Browse the repository at this point in the history
  • Loading branch information
kuba-kubula committed Feb 26, 2015
2 parents 235d169 + ff0ecd5 commit aa6faaf
Show file tree
Hide file tree
Showing 15 changed files with 826 additions and 208 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
node_modules
src-cov
/lib
cov.html
.vagrant
*.DS_Store
/.idea
Expand Down
94 changes: 10 additions & 84 deletions bin/dredd
Original file line number Diff line number Diff line change
@@ -1,87 +1,13 @@
#!/usr/bin/env node
var optimist = require('optimist');
var parsePackageJson = require('../lib/parse-package-json');
var path = require('path');
var Dredd = require('../lib/dredd');

var version = parsePackageJson(path.join(__dirname, '../package.json'));

var argv = optimist
.usage("Usage: \n dredd <path or URL to blueprint> <api_endpoint> [OPTIONS]" +
"\n\nExample: \n " + "dredd ./apiary.md http://localhost:3000 --dry-run")
.options(Dredd.options)
.wrap(80)
.argv;

var argError = false;

if (argv.help === true) {
optimist.showHelp(fn=console.error);
process.exit(0);
}

if (argv.version === true) {
console.log(version);
process.exit(0);
}

if (argv._[0] === undefined) {
console.error("Error: Must specify path to blueprint file.");
argError = true;
}
if (argv._[1] === undefined) {
console.error("Error: Must specify api endpoint.");
argError = true;
}

if (argError) {
console.error("\n");
optimist.showHelp(fn=console.error);
process.exit(1);
}

// transform path and p argument to array if it's not
if(!Array.isArray(argv['path'])){
argv['path'] = argv['p'] = [argv['path']];
}

// some shells are automatically expanding globs and concating result as arguments
// so I'm taking last argument as API endpoint server URL and removing it forom optimist's args
var server = argv._[argv._.length - 1];
argv._.splice(argv._.length -1, 1);

// and rest of arguments concating to 'path' and 'p' opts, duplicates are filtered out later
argv['p'] = argv['path'] = argv['path'].concat(argv._)

configuration = {
'server': server,
'options': argv
};

configuration.options.path.push(argv._[0]);

dredd = new Dredd(configuration);

process.on( 'SIGINT', function() {
console.log( "\nShutting down from SIGINT (Ctrl-C)" );
dredd.transactionsComplete(function() {
process.exit(0);
});
var DreddCommand = require('../lib/command');

var dreddCli = new DreddCommand({
custom: {
env: process.env,
cwd: process.cwd(),
argv: process.argv.slice(2)
},
exit: process.exit
});

dredd.run(function(error, stats){
if (error) {
if (error.message) {
console.error(error.message);
}
if (error.stack) {
console.error(error.stack);
}
process.exit(1);
}
if (stats.failures + stats.errors > 0) {
process.exit(1);
} else {
process.exit(0);
}
});
dreddCli.warmUp().takeoff();
7 changes: 3 additions & 4 deletions src/add-hooks.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ require 'coffee-script/register'
proxyquire = require('proxyquire').noCallThru()
glob = require 'glob'
async = require 'async'

hooks = require './hooks'
logger = require './logger'

addHooks = (runner, transactions, emitter) ->
addHooks = (runner, transactions, emitter, customConfig) ->
@emitter = emitter

for transaction in transactions
Expand All @@ -23,7 +22,7 @@ addHooks = (runner, transactions, emitter) ->

try
for file in files
proxyquire path.resolve(process.cwd(), file), {
proxyquire path.resolve((customConfig?.cwd or process.cwd()), file), {
'hooks': hooks
}
catch error
Expand Down Expand Up @@ -80,6 +79,6 @@ addHooks = (runner, transactions, emitter) ->
title: transaction.id
message: transaction.name
origin: transaction.origin
@emitter.emit 'test error', error, test if error
@emitter?.emit 'test error', error, test if error

module.exports = addHooks
39 changes: 28 additions & 11 deletions src/apply-configuration.coffee
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
{EventEmitter} = require 'events'
clone = require 'clone'

logger = require './logger'

applyConfiguration = (config) ->
coerceToArray = (value) ->
if Array.isArray value
return value
else if typeof value is 'string'
return [value]
else if !value?
return []
else
return value

coerceToArray = (value) ->
if typeof value is 'string'
value = [value]
else if !value?
value = []
else if value instanceof Array
value
else value
applyConfiguration = (config) ->

configuration =
blueprintPath: null
server: null
emitter: new EventEmitter
custom: { # used for custom settings of various APIs or reporters
# Keep commented-out, so these values are actually set by DreddCommand
# env: {}
# stdout: process.stdout
# cwd: process.cwd()
}
options:
'dry-run': false
silent: false
Expand All @@ -36,9 +44,18 @@ applyConfiguration = (config) ->
names: false
hookfiles: null

#normalize options and config
# normalize options and config
for own key, value of config
configuration[key] = value
# copy anything except "custom" hash
if key isnt 'custom'
configuration[key] = value
else
configuration[key] = {}
for customKey, customVal of value or {}
if customKey in ['env', 'cwd']
configuration[key][customKey] = clone customVal, false
else if customKey is 'stdout'
configuration[key][customKey] = customVal

#coerce single/multiple options into an array
configuration.options.reporter = coerceToArray(configuration.options.reporter)
Expand Down
158 changes: 158 additions & 0 deletions src/command.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
path = require 'path'
optimist = require 'optimist'
console = require 'console'

parsePackageJson = require './parse-package-json'
Dredd = require './dredd'

version = parsePackageJson path.join(__dirname, '../package.json')

class DreddCommand
constructor: (options = {}, @cb) ->
{@exit, @custom} = options
# support to call both 'new DreddCommand()' and/or 'DreddCommand()'
# without the "new" keyword
@custom ?= {}

if not @custom.cwd or typeof @custom.cwd isnt 'string'
@custom.cwd = process.cwd()

if not @custom.argv or not Array.isArray @custom.argv
@custom.argv = []

if not (@ instanceof DreddCommand)
return new DreddCommand(options, @cb)

@finished = false

warmUp: ->
@finished = false

@optimist = optimist(@custom['argv'], @custom['cwd'])

@optimist.usage(
"""
Usage:
dredd <path or URL to blueprint> <api_endpoint> [OPTIONS]
Example:
dredd ./apiary.md http://localhost:3000 --dry-run
"""
)
.options(Dredd.options)
.wrap(80)

@argv = @optimist.argv

argError = false

if not @cb
@exit and (@exit is process.exit) and @sigIntEventAdd = true
@_processExit = @exit or process.exit
else
@_processExit = ((code) ->
if @finished then return
@finished = true
if @sigIntEventAdded
process.removeEventListener 'SIGINT', @commandSigInt
@cb code
return @
).bind @

if @argv.help is true
@optimist.showHelp(console.error)
return @_processExit(0)

if @argv.version is true
console.log version
return @_processExit(0)

if not @argv._[0]?
console.error("\nError: Must specify path to blueprint file.")
argError = true

if not @argv._[1]?
console.error("\nError: Must specify api endpoint.")
argError = true

if argError
console.error("\n")
@optimist.showHelp(console.error)
return @_processExit(1)

# transform path and p argument to array if it's not
if !Array.isArray(@argv['path'])
@argv['path'] = @argv['p'] = [@argv['path']]

configurationForDredd = @initConfig()
@dreddInstance = @initDredd configurationForDredd
return @

lastArgvIsApiEndpoint: ->
# some shells are automatically expanding globs and concating result as arguments
# so I'm taking last argument as API endpoint server URL and removing it forom optimist's args
@server = @argv._[@argv._.length - 1]
@argv._.splice(@argv._.length - 1, 1)
return @

takeRestOfParamsAsPath: ->
# and rest of arguments concating to 'path' and 'p' opts, duplicates are filtered out later
@argv['p'] = @argv['path'] = @argv['path'].concat(@argv._)
return @

initConfig: ->
@
.lastArgvIsApiEndpoint()
.takeRestOfParamsAsPath()

configuration =
'server': @server
'options': @argv

# push first argument (without some known configuration --key) into paths
configuration.options.path ?= []
configuration.options.path.push @argv._[0]

if @custom['env'] or @custom['stdout'] or @custom['cwd']
configuration.custom ?= {}
configuration.custom['env'] = @custom['env'] or process.env
configuration.custom['stdout'] = @custom['stdout'] or process.stdout
configuration.custom['cwd'] = @custom['cwd'] or process.cwd()

return configuration

initDredd: (configuration) ->
dredd = new Dredd configuration
return dredd

commandSigInt: ->
console.log "\nShutting down from SIGINT (Ctrl-C)"
@dreddInstance.transactionsComplete => @_processExit(0)

takeoff: ->
if @finished then return

@runDredd @dreddInstance

runDredd: (dreddInstance) ->
if @sigIntEventAdd
# handle SIGINT from user
@sigIntEventAdded = !@sigIntEventAdd = false
process.on 'SIGINT', @commandSigInt

dreddInstance.run (error, stats) =>
if error
if error.message
console.error error.message
if error.stack
console.error error.stack
return @_processExit(1)
if (stats.failures + stats.errors) > 0
@_processExit(1)
else
@_processExit(0)
return

return @

exports = module.exports = DreddCommand
17 changes: 8 additions & 9 deletions src/configure-reporters.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,18 @@ configureReporters = (config, stats, tests) ->
when 'junit'
xUnitReporter = new XUnitReporter(emitter, stats, tests, path, config.options.details)
when 'dot'
dotReporter = new DotReporter(emitter, stats, tests)
dotReporter = new DotReporter(emitter, stats, tests, config)
when 'nyan'
nyanCatReporter = new NyanCatReporter(emitter, stats, tests)
nyanCatReporter = new NyanCatReporter(emitter, stats, tests, config)
when 'html'
htmlReporter = new HtmlReporter(emitter, stats, tests, path, config.options.details)
when 'markdown'
mdReporter = new MarkdownReporter(emitter, stats, tests, path, config.options.details)
when 'apiary'
apiaryReporter = new ApiaryReporter(emitter, stats, tests)
else
logger.warn "Invalid reporter #{reporter} selected, ignoring."
apiaryReporter = new ApiaryReporter(emitter, stats, tests, config)
# else
# Cannot happen, due to 'intersection' usage
# logger.warn "Invalid reporter #{reporter} selected, ignoring."


addCli(reporters) if not config.options.silent
Expand All @@ -57,14 +58,12 @@ configureReporters = (config, stats, tests) ->

if usedFileReporters.length > 0
usedFileReportersLength = usedFileReporters.length
if reporters.indexOf('apiary') != -1
if reporters.indexOf('apiary') > -1
usedFileReportersLength = usedFileReportersLength - 1
if process.env['DREDD_REST_TOKEN'] == undefined or process.env['DREDD_REST_SUITE'] == undefined
logger.warn "Apiary reporter environment variable DREDD_REST_TOKEN or DREDD_REST_SUITE not defined."

if usedFileReportersLength > outputs.length
logger.warn """
There are more reporters requiring output paths than there are output paths
There are more reporters requiring output paths than there are output paths \
provided, using default paths for additional file-based reporters.
"""

Expand Down
Loading

0 comments on commit aa6faaf

Please sign in to comment.