Dialect Definitions for: 1.2.1
Show:

File: node_modules/meta4qa-common/lib/dialect/variables.js

var assert = require('assert');
var request = require('request');
var _ = require('underscore');
var fs = require('fs');
var path = require('path');
var debug = require('debug')('meta4qa:dialect:variables');

var meta4qa = require('meta4qa'),
    helps = meta4qa.helpers,
    vars = helps.vars,
    files = helps.files,
    converts = meta4qa.converts,
    http = helps.http;
/**
 * Variables
 * Configures the Gherkin parser with phrases that support operations on variables
 *
 * @module Default Dialect
 * @class Variables
 *
 */

var self = module.exports = function(learn, config, dialect) {
    assert(learn, "missing learn");
    assert(config, "missing config");
    assert(dialect, "missing dialect");
    assert(helps, "missing helpers");

    // ***** GIVEN *****

    /**
     * Remove all the scoped variables
     *
     *      I clear variables
     *
     *      I reset variables
     *
     * @example
     *
     *      GIVEN I reset variables
     *      
     * @method Clear Variables
     */

    learn.given(["I clear variables", "I reset variables"], function(done) {
        for (var name in this.vars) delete this.vars[name];
        done && done();
    });

    /**
     * Set the value of a scoped variable
     *
     *      I set $varname to $value
     *
     *      I set $varname = $value
     *
     *      I define $varname = $value
     *
     *      I define $varname is $value
     *
     * @example
     *
     *      GIVEN I set hello to world
     *      AND I set yes to true
     *      AND I set nope to false
     *      AND I set answer to 42
     *
     * @method Set Variable
     * @param {String} variable - variable name
     * @param {Object} value - simple value (string | number | boolean)
     */

    learn.given(["I set $varname to $value", "I set $varname = $value", "I define $varname = $value", "I define $varname is $value"], function(name, value, done) {
        vars.set(this.vars, name, value);
        done && done();
    });

    learn.given(["I set $varname from $varname2"], function(name, var2, done) {
        var value = vars.find(this, var2);
        assert(value!=undefined, "Value "+name+" is undefined");
        vars.set(this.vars, name, value);
        done && done();
    });

    // learn.given(["I randomize $varname with $size characters"], function(name, size, done) {
    //     var value = vars.find(this, name);
    //     assert(value!=undefined, "Value "+name+" is undefined");
    //     vars.set(this.vars, name, value);
    //     done && done();
    // });

    learn.given(["I want it $varname", "I want a $varname", "I want an $varname"], function(name, done) {
        vars.set(this.vars, name, true);
        done && done();
    });

    learn.given(["I convert $varname to text"], function(name, done) {
        var original = vars.find(this,name);
        vars.set(this.vars,name, JSON.stringify(original));

        done && done();
    });

    /**
     * Sets the value of a scoped variable to inline CSV data structure
     *
     *      I set $varname to CSV:
     *      -------------
     *      $CSV
     *      -------------
     *
     *      some $varname as CSV:
     *      -------------
     *      $CSV
     *      -------------
     *
     * @example
     *
     *      GIVEN I set my-csv to CSV:
     *      -------------
     *      hello, goodbye
     *      world, earth
     *      -------------
     *
     *  or:
     *
     *      AND some CSV as my-csv:
     *      -------------
     *      hello, goodbye
     *      world, earth
     *      -------------
     *
     *
     * @method Set Variable from CSV
     * @param {String} name - variable name
     * @param {string} CSV - inline CSV text
     */

    learn.given(["I set $varname to CSV:\n$CSV", "some CSV as $varname:\n$CSV"], function(varname, csv, done) {
        vars.set(this.vars, varname, csv);
        done && done();
    });

    /**
     * Sets the value of a scoped variable to inline JSON data structure
     * ---------- ---------- ---------- ----------
     *
     * @example
     *
     *      GIVEN I set $varname to JSON:
     *      -------------
     *      { "hello": "world" }
     *      -------------
     *
     *  or:
     *
     *      AND some JSON as $varname:
     *      -------------
     *      { "hello": "world" }
     *      -------------
     *
     *
     * @method Set Variable from JSON
     * @param {String} name - variable name
     * @param {Object} JSON - inline JSON
     */

    learn.given(["I set $varname to JSON:\n$JSON", "some JSON as $varname:\n$JSON"], function(name, json, done) {
        vars.set(this.vars, name, json);
        done && done();
    });

    learn.given(["I set $varname to text:\n$TEXT", "some text as $varname:\n$TEXT"], function(name, text, done) {
        vars.set(this.vars, name, text);
        done && done();
    });

    /**
     * Run Javscript and save result into a variable
     *
     * @example
     *
     *      GIVEN I return 2+3 as my-answer
     *
     *      AND I return new Date().getTime() as now

     * @method Save Javascript to Variable
     * @param {String} javascript - inline javascript
     * @param {string} varname - variable name
     */

    learn.given("I return $javascript as $varname", function(js, name, done) {
        var fn = new Function("return ("+js+");");
        var result = fn.apply(this, arguments);
        vars.set(this.vars, name, result);
        done && done();
    });

    /**
     * Execute Javascript - trigger a fail if return is falsey
     *
     * @example
     *
     *      WHEN I execute (3+4)
     *
     * @method Execute Javascript
     * @param {String} javascript - inline javascript
     */

    learn.when(["I execute $javascript", "I execute\n$javascript"], function(js, done) {
        var fn = new Function(js);
        var result = fn.apply(this);
        if (typeof(result) != "undefined") {
            assert(result, "Javascript return 'falsey'");
        }
        done && done();
    });

    /**
     * Assert some Javascript returns true or trigger a fail if return is 'falsey'
     *
     * @example
     *
     *      GIVEN I am testing
     *      THEN I assert this.name == "testing"
     *
     * @method Assert Javascript
     * @param {String} javascript - inline javascript
     */

    learn.then(["I assert $javascript","I expect $javascript"], function(js, done) {
//console.log("VARS: %s -> %j", js, _.keys(this));
        var fn = new Function("return ("+js+");");
        var result = fn.apply(this);
        assert(result, "Javascript assert: "+js+" --> "+result);
        done && done();
    });

    /**
     * Assert some variable is assigned a value that is truthy
     *
     *      variable $varname should exist
     *
     * @example
     *
     *      GIVEN I set variable hello to world
     *      THEN variable hello should exist
     *
     * @method Assert variable is truthy
     * @param {String} varname - scoped variable
     */

    learn.then(["variable $varname should exist", "variable $varname exists", "$varname should exist", "$varname exists"], function(name, done) {
        var value = vars.find(this, name);

        assert(value, "Variable "+name+" does not exist");
        assert(value!=undefined, "Variable "+name+" does not exist");
        done && done();
    });

    /**
     * Assert some variable should match an exact value
     *
     *
     *      variable $varname should be $value
     *      $varname should be $value
     *      $varname equals $value
     *      $varname is $value
     *      $varname = $value
     *
     * @example
     *
     *      GIVEN I set variable hello to world
     *      THEN variable hello should exist
     *
     * @method Assert variable matches a value exactly
     * @param {String} varname - scoped variable
     * @param {String} value - expected value
     */

    learn.then(["variable $varname should be $value", "$varname should be $value", "$varname equals $value", "$varname must equal $value", "$varname = $value" ], function(name, value, done) {

        if (value=="true") value = true;
        else if (value=="false") value = false;
        var v = vars.findNamed(this, name);
        assert(v != undefined, "Variable ["+name+"] does not exist -> "+this.vars[name]);
        assert(v==value, "Variable "+name+" does not equal "+value);
        done && done();
    });

    /**
     * Assert some variable should contain a value
     *
     *
     *      variable $varname should contain $value
     *
     * @example
     *
     *      GIVEN I set variable hello to world
     *      THEN variable hello should contain orl
     *
     * @method Assert variable value contains some string
     * @param {String} varname - scoped variable
     * @param {String} value - expected value
     */

    learn.then("variable $varname should contain $value", function(name, value, done) {
        var v = vars.get(this.vars,name);
        assert(v, "Variable "+name+" does not exist");
        assert(v.indexOf(value)>0, "Variable "+name+" does not contain "+value);
        done && done();
    });

    /**
     * Assert some variable should match a regular expression (RegExp)
     *
     *
     *      variable $varname should match $regex
     *
     * @example
     *
     *      GIVEN I set variable hello to world
     *      THEN variable hello should match a-z
     *
     * @method Assert variable matches RegExp
     * @param {String} varname - scoped variable
     * @param {String} regex - regular expression
     */

    learn.then(["variable $varname should match $regex", "variable $varname must match $regex"], function(name, regex, done) {
        var v = vars.findNamed(this,name);
        assert(v, "Variable "+name+" does not exist");
        var re = new RegExp(regex);
        assert(re.test(v), "Variable "+name+" does not match "+regex);
        done && done();
    });

    /**
     * Assert some JSON path should match a regular expression (RegExp)
     *
     *
     *      variable $varname should match $regex
     *
     * @example
     *
     *      GIVEN I set variable hello to world
     *      THEN variable hello should match a-z
     *
     * @method Assert variable matches RegExp
     * @param {String} varname - scoped variable
     * @param {String} regex - regular expression
     */

    learn.then(["$path should match $regex", "$path matches $regex", "$path must match $regex"], function(name, regex, done) {
        var v = vars.findNamed(this,name);
        assert(v, "Variable "+name+" does not exist");
        var re = new RegExp(regex);
        assert(re.test(v), "Variable "+name+" does not match "+regex);
        done && done();
    });


    /**
     * Assert some JSON path within a complex variable should match a regular expression (RegExp)
     *
     *
     *      $.hello in $varname should match $regex
     *
     * @example
     *
     *      GIVEN I set variable my.hello to world
     *      THEN $.hello in my should match a-z
     *
     * @method Assert JSON path matches RegExp
     * @param {String} path- JSON path
     * @param {String} varname - scoped variable
     * @param {String} regex - regular expression
     */

    learn.then(["$path in $varname should match $regex", "$path in $varname must match $regex", "$path in $varname matches $regex"], function(path, name, regex, done) {
        var value = vars.findNamed(this, name);
//        debug("VALUE: %j in %s -> %j", value, name, this);
        assert(value, "Variable "+name+" does not exist");
//        debug("found: %s -> %j", name, value);
        var found = vars.findInPath(value, path);
debug("found: %s in %s -> %j", path, name, found);
        assert(found, "Path "+path+" not found in "+name);
        var re = new RegExp(regex);
        assert(re.test(found), "No path "+path+" in "+name+" matches "+regex);
        done && done();
    });

    /**
     * Assert that any array element in JSON path within a variable should match a regular expression (RegExp)
     *
     *
     *      $.hello in $varname should match $regex
     *
     * @example
     *
     *      GIVEN I set variable my.hello to world
     *      THEN any $.hello in my should match a-z
     *
     * @method Assert JSON path matches RegExp
     * @param {String} path - a valid JSON path
     * @param {String} varname - scoped variable
     * @param {String} regex - regular expression
     */

    learn.then(["any $path in $varname should match $regex", "any $path in $varname must match $regex", "any $path in $varname matches $regex"], function(path, name, regex, done) {
        var value = vars.findNamed(this, name);
//        debug("VALUE: %j in %s -> %j", value, name, this);
        assert(value, "Variable "+name+" does not exist");
//        debug("found: %s -> %j", name, value);
        var found = vars.findAllInPath(value, path);
        assert(found, "Path "+path+" not found in "+name);

        if (!_.isArray(found)) found = [found];
        debug("found all: %s in %s -> %j", path, name, found);

        var re = new RegExp(regex);
        var passed = false;
        _.each(found, function(value) {
            passed = passed?passed:re.test(value);
        })
        assert(passed, "No path "+path+" in "+name+" matches "+regex);
        done && done();
    });

    // **********************************************************************
    // * 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");
    }

    debug("understands variables");
    return self;
}