apigeek-dialect
Advanced tools
Comparing version 1.0.5 to 1.0.6
{ | ||
"featuresPath": "./features", | ||
"files": "./features/files", | ||
"init": true, | ||
"repeat": 1, | ||
"target": {}, | ||
@@ -11,2 +9,2 @@ "targets": {}, | ||
"certificates": {} | ||
} | ||
} |
@@ -10,3 +10,3 @@ var cli = require("commander"); | ||
option("--files <path>", "folder containing support files"). | ||
option("--init", "create initial files (apigeek.json) and folders (./features)."). | ||
option("--initialize", "create initial files (apigeek.json) and folders (./features)."). | ||
option("--example", "create some examples in ./features"). | ||
@@ -13,0 +13,0 @@ option("--knows", "display supported phrases"). |
@@ -9,14 +9,28 @@ var fs = require('fs'); | ||
var debug = require("debug")("apigeek:cli"); | ||
var Engine = require("./Engine"); | ||
var defaults = require("./defaults"); | ||
var Dialect = require("./Dialect"); | ||
module.exports = function(cli) { | ||
assert(cli, "missing CLI") | ||
cli.parse(process.argv); | ||
assert(cli, "missing CLI/config") | ||
this.PROTECTED_CONFIG = ["configFile", "mocha", "yadda", "name", "initialize", "example", "repeat", "commands", "options" ]; | ||
// load / init configuration | ||
var config = config || {}; | ||
var config = {}; | ||
// if we've passed a CLI - then parse args | ||
if (cli.parse) { | ||
cli.parse && cli.parse(process.argv); | ||
// cli options become config defaults | ||
// config = _.omit(cli, PROTECTED_CONFIG); | ||
_.each(cli.options, function(option) { | ||
var flag = option.name(); | ||
if (cli[flag]) config[flag] = cli[flag]; | ||
}) | ||
} else { | ||
_.extend(config, cli); | ||
} | ||
config.configFile = cli.config || 'apigeek.json'; | ||
@@ -26,3 +40,5 @@ config.featuresPath = cli.tests || cli.features || "./features"; | ||
config = _.defaults(config, defaults); | ||
if (helpers.files.exists(config.configFile)) { | ||
debug("Configuring from: %s ==> %s", config.configFile, helpers.files.exists(config.configFile)); | ||
try { | ||
@@ -35,13 +51,7 @@ _.extend(config, JSON.parse(fs.readFileSync(config.configFile, 'utf8'))); | ||
} else { | ||
if (!cli.example && cli.init) | ||
if (!cli.example && cli.init) { | ||
console.log("warning: default configuration. Create " + config.configFile + " or use --config <file>. If it's your first time, use the --example option"); | ||
} | ||
} | ||
// cli options become config defaults | ||
_.each(cli.options, function(option) { | ||
var flag = option.name(); | ||
if (cli[flag]) config[flag] = cli[flag]; | ||
}) | ||
// --target overrides default target | ||
@@ -53,3 +63,3 @@ | ||
config.repeat = cli.repeat?cli.repeat+1:1; | ||
config.repeat = cli.repeat?(1+new Number(cli.repeat)):1; | ||
@@ -56,0 +66,0 @@ // archive path |
@@ -21,3 +21,3 @@ var Yadda = require('yadda'); // https://github.com/acuminous/yadda | ||
var self = this, vocabs = {}, installed = {}, scope = {}; | ||
var self = this, vocabs = {}, controllers = {}, scope = {}; | ||
@@ -79,2 +79,5 @@ this.config = _.defaults(config, require("./defaults")); | ||
// Dynamically load internal Dialects | ||
this.vocab = function(stepsDir) { | ||
@@ -90,8 +93,12 @@ assert(stepsDir, "Missing dialect folder"); | ||
// Test if a Dialect controlled is controllers | ||
this.known = function(name) { | ||
var fn = installed[name]; | ||
var fn = controllers[name]; | ||
if (!_.isFunction(fn)) return false; | ||
return installed[name]?true:false; | ||
return controllers[name]?true:false; | ||
} | ||
// Register a named Dialect function | ||
this.learn = function(fn, name) { | ||
@@ -105,3 +112,3 @@ assert(fn, "Missing learn fn()"); | ||
debug("ignored duplicate dialect: "+name); | ||
return installed; | ||
return controllers; | ||
} | ||
@@ -111,9 +118,11 @@ vocabs[name] = fn; | ||
installed[name] = fn(self.library, self.config, scope ); | ||
assert(installed[name], "not installed: "+name); | ||
controllers[name] = fn(self.library, self.config, scope ); | ||
assert(controllers[name], "not controllers: "+name); | ||
debug("knows "+name); | ||
return installed; | ||
return controllers; | ||
} | ||
// Require a Dialect by path | ||
this.requires = function(required) { | ||
@@ -138,9 +147,11 @@ var items = _.isArray(required)?required:[]; | ||
// Registered Dialect Controllers | ||
this.annotations = function(annotations, scope, scope2) { | ||
assert(scope, "missing scope"); | ||
assert(annotations, "missing annotations"); | ||
assert(installed, "missing dialects"); | ||
assert(controllers, "missing Dialect controllers"); | ||
_.each(installed, function(vocab, name) { | ||
if (!vocab) error("Missing annotations: "+name); | ||
_.each(controllers, function(vocab, name) { | ||
if (!vocab) error("Missing dialect controller: "+name); | ||
vocab.annotations && vocab.annotations(self, annotations, scope, scope2); | ||
@@ -151,2 +162,26 @@ }); | ||
this.scenario = function(scope) { | ||
assert(scope, "missing scope"); | ||
assert(controllers, "missing Dialect controllers"); | ||
_.each(controllers, function(vocab, name) { | ||
if (!vocab) error("Missing dialect controller: "+name); | ||
vocab.scenario && vocab.scenario(self, scope); | ||
}); | ||
return self; | ||
} | ||
this.feature = function(scope) { | ||
assert(scope, "missing scope"); | ||
assert(controllers, "missing Dialect controllers"); | ||
_.each(controllers, function(vocab, name) { | ||
if (!vocab) error("Missing dialect controller: "+name); | ||
vocab.feature && vocab.feature(self, scope); | ||
}); | ||
return self; | ||
} | ||
// Return an array of parsed features | ||
this.audit = function(stepsDir) { | ||
@@ -161,2 +196,4 @@ assert(stepsDir, "Missing features to audit"); | ||
// Load and Parse a feature definition | ||
this.load = function(file, found) { | ||
@@ -177,2 +214,4 @@ assert(file, "missing file"); | ||
// Do we support the Feature extension | ||
this.supports = function(file) { | ||
@@ -190,2 +229,5 @@ var ext = file.lastIndexOf("."); | ||
// | ||
// Parse a Feature definition into JSON | ||
this.parse = function(file) { | ||
@@ -201,2 +243,4 @@ assert(file, "Missing feature file"); | ||
// Execute a phrase | ||
this.execute = function(phrase, scope, done) { | ||
@@ -208,2 +252,3 @@ assert(phrase, "Missing phrase"); | ||
// Get the title for the Feature | ||
this.title = function(title) { | ||
@@ -213,6 +258,7 @@ return title || "Feature"; | ||
this.noop = function(model) { | ||
if (!model) return false; | ||
if (config.debug && model.bug) delete model.bug; | ||
return vars.synonym(model,NOOPS); | ||
// test if scope contains an annotation that implies No-Operation | ||
this.noop = function(scope) { | ||
if (!scope) return false; | ||
if (config.debug && scope.bug) delete model.bug; | ||
return vars.synonym(scope,NOOPS); | ||
} | ||
@@ -219,0 +265,0 @@ |
@@ -24,2 +24,5 @@ var assert = require("assert"); | ||
// since not all plug-ins are well-behaved - we'll be forgiving ... | ||
self.runner.ignoreLeaks = true; | ||
var Reporter = config.reporter && _.isFunction(config.reporter)?config.reporter:Mocha.reporters[config.reporter||"spec"]; | ||
@@ -49,3 +52,3 @@ self.reporter = new Reporter(self.runner, config); | ||
self.emit("start", self); | ||
self.emit("start", epic, self); | ||
self.started = _.now(); | ||
@@ -55,3 +58,2 @@ self.runner.run(function(results) { | ||
self.elapsed = self.stopped - self.started; | ||
if (results>0) { | ||
@@ -64,4 +66,5 @@ results = { stats: { failures: results } }; | ||
results = results || (self.runner.testResults?self.runner.testResults: {stats: self.reporter.stats }); | ||
debug("actioned "+results.stats.passes+" stories in "+self.elapsed+"ms"); | ||
self.emit("finished", results, epic); | ||
debug("actioned "+results.stats.passes+" feature(s) in "+self.elapsed+"ms"); | ||
self.emit("finished", results, epic, self); | ||
done && done(results, epic) | ||
@@ -68,0 +71,0 @@ }); |
@@ -8,3 +8,3 @@ var Events = require('events'); | ||
module.exports = function(dialect, feature, scope) { | ||
module.exports = function(dialect, feature, config) { | ||
assert(dialect, "Missing dialect"); | ||
@@ -14,4 +14,6 @@ assert(dialect.execute, "Dialect can't execute"); | ||
assert(feature.title, "Missing feature title"); | ||
scope = scope || {}; | ||
var scope = config || {}; | ||
//debug("Init: %j", scope); | ||
var self = this; | ||
@@ -27,7 +29,11 @@ _.extend(this, new Events()); | ||
//debug("Story: %j", scope); | ||
var story = new Mocha.Test(scenario.title, function (done) { | ||
self.emit("story start", story, scenario); | ||
debug(scenario.title); | ||
// run each step synchronously | ||
var i = 1; | ||
async.eachSeries(scenario.steps, function (step, stepDone) { | ||
debug(step); | ||
debug("%s) %s", i++, step); | ||
dialect.execute(step, scope, stepDone); | ||
@@ -58,3 +64,5 @@ self.emit("story step", step, story, scenario); | ||
scope = _.extend({ vars: {} }, scope, { name: "story" }); | ||
var scope = _.extend({}, config, { vars: {}, name: "feature" }); | ||
//debug("Feature 2: %j", scope); | ||
dialect.annotations(feature.annotations, scope, suite); | ||
@@ -65,7 +73,7 @@ | ||
_.each(feature.scenarios, function (scenario) { | ||
var feature_scope = _.extend({ scenario: scenario }, scope); | ||
var scenario_scope = _.extend({}, scope, { name: "scenario"}); | ||
if (!dialect.noop(scenario.annotations)) { | ||
var story = self.story(scenario, feature_scope); | ||
var story = self.story(scenario, scenario_scope); | ||
suite.addTest(story); | ||
@@ -72,0 +80,0 @@ self.emit("story", story, scenario); |
@@ -18,4 +18,2 @@ #!/usr/bin/env node | ||
const PROTECTED_CONFIG = ["configFile", "mocha", "yadda", "name"]; | ||
var self = module.exports = _.extend({ | ||
@@ -44,2 +42,4 @@ Feature: require("./Feature"), | ||
} | ||
self.engine = new self.Engine(self.config); | ||
} | ||
@@ -66,5 +66,7 @@ | ||
if ( (self.cli.init || self.cli.example)) { | ||
// initialize / write example files | ||
if ( (self.cli.initialize || self.cli.example)) { | ||
mkdirp(self.config.featuresPath); | ||
self.helpers.build.json(self.config.configFile, _.omit(self.config, PROTECTED_CONFIG )); | ||
self.helpers.build.json(self.config.configFile, _.omit(self.config, self.configure.PROTECTED_CONFIG )); | ||
@@ -81,2 +83,3 @@ if (self.cli.example) { | ||
// return a JSON object of the parsed features | ||
if (self.cli.audit) { | ||
@@ -88,10 +91,8 @@ var audit = self.dialect.audit(self.config.featuresPath); | ||
// pre-flight | ||
// warn if no explict ./features folder | ||
if (!self.helpers.files.exists(config.featuresPath)) { | ||
console.log("missing "+config.featuresPath+" folder. Create it manually or use the --init option"); | ||
console.log("missing "+config.featuresPath+" folder. Create it manually or use the --inititalize / --example options"); | ||
return; | ||
} | ||
self.engine = new self.Engine(self.config); | ||
// repeat tests | ||
@@ -106,3 +107,3 @@ async.times(config.repeat, function (n, next) { | ||
var onComplete = function (results, feature) { | ||
debug("done: " + results.stats.failures + " failed"); | ||
// save results (and runtime options) to file | ||
@@ -116,2 +117,3 @@ if (config.archive) { | ||
} | ||
// only exist with status code when running once - | ||
@@ -121,3 +123,6 @@ // TODO: SVT (--repeat) do not exist cleanly | ||
if (config.repeat==1) { | ||
debug("exit: " + results.stats.failures + " failed"); | ||
process.exit(results.stats.failures); | ||
} else { | ||
debug("done: " + results.stats.failures + " failed"); | ||
} | ||
@@ -131,6 +136,6 @@ } | ||
self.auto = function() { | ||
self.auto = function(cli) { | ||
if (require.main === module) { | ||
// ran from command line | ||
self.init(self.cli); | ||
self.init(cli || self.cli); | ||
debug("running: "+self.helpers.pkg.name); | ||
@@ -137,0 +142,0 @@ self.execute(); |
@@ -18,2 +18,15 @@ var assert = require('assert'); | ||
// Dialect Controller | ||
self.feature = function(dialect, scope) { | ||
assert(dialect, "missing dialect"); | ||
assert(scope, "missing scope"); | ||
}; | ||
self.scenario = function(dialect, scope) { | ||
assert(dialect, "missing dialect"); | ||
assert(scope, "missing scope"); | ||
}; | ||
self.annotations = function(dialect, annotations, scope) { | ||
@@ -20,0 +33,0 @@ } |
@@ -39,10 +39,8 @@ var assert = require('assert'); | ||
var found = helps.vars.get(this, name) || helps.vars.get(this.vars, name); | ||
console.log("\t%s ==> %j\n", name, found ); | ||
log("\t%s ==> %j\n", name, found ); | ||
done && done(); | ||
}); | ||
learn.then(["dump"], function(done) { | ||
console.log("DUMP: %j", this); | ||
learn.then(["dump", "I dump"], function(done) { | ||
log("DUMP: %j", this); | ||
done && done(); | ||
@@ -86,2 +84,16 @@ }); | ||
// Dialect Controller | ||
self.feature = function(dialect, scope) { | ||
assert(dialect, "missing dialect"); | ||
assert(scope, "missing scope"); | ||
}; | ||
self.scenario = function(dialect, scope) { | ||
assert(dialect, "missing dialect"); | ||
assert(scope, "missing scope"); | ||
}; | ||
self.annotations = function(dialect, annotations, scope) { | ||
@@ -94,2 +106,3 @@ assert(dialect, "missing dialect"); | ||
// dynamic dialects | ||
var dialects = []; | ||
@@ -102,2 +115,3 @@ if (_.isString(annotations.dialects)) dialects.push(annotations.dialects); | ||
dialect.requires(dialects); | ||
scope.dialects = dialects; | ||
} | ||
@@ -104,0 +118,0 @@ |
@@ -94,2 +94,17 @@ var assert = require('assert'); | ||
// Dialect Controller | ||
self.feature = function(dialect, scope) { | ||
assert(dialect, "missing dialect"); | ||
assert(scope, "missing scope"); | ||
}; | ||
self.scenario = function(dialect, scope) { | ||
assert(dialect, "missing dialect"); | ||
assert(scope, "missing scope"); | ||
}; | ||
self.annotations = function(dialect, annotations, scope) { | ||
@@ -96,0 +111,0 @@ } |
@@ -112,3 +112,19 @@ var assert = require('assert'); | ||
// Dialect Controller | ||
self.feature = function(dialect, scope) { | ||
assert(dialect, "missing dialect"); | ||
assert(scope, "missing scope"); | ||
}; | ||
self.scenario = function(dialect, scope) { | ||
assert(dialect, "missing dialect"); | ||
assert(scope, "missing scope"); | ||
}; | ||
self.annotations = function(dialect, annotations, scope) { | ||
assert(dialect, "missing dialect"); | ||
assert(annotations, "missing annotations"); | ||
assert(scope, "missing scope"); | ||
} | ||
@@ -115,0 +131,0 @@ |
{ | ||
"name": "apigeek-dialect", | ||
"version": "1.0.5", | ||
"version": "1.0.6", | ||
"description": "A Gherkin-based micro-framework", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
Sorry, the diff of this file is not supported yet
102844
1504