/**
* BDD EDSL for the Specify framework.
*
* @module specify-dsl-bdd/lib/core
*/
// -- Dependencies -----------------------------------------------------
var Future = require('data.future');
var Maybe = require('data.maybe');
var Async = require('control.async')(Future);
var Lambda = require('core.lambda');
var Base = require('boo').Base;
var adt = require('adt-simple');
// -- Aliases ----------------------------------------------------------
var curry = Lambda.curry;
var fail = Future.rejected;
var fromPromise = Async.fromPromise;
var liftNode = Async.liftNode;
// -- Core implementation ----------------------------------------------
/**
* A list of supported implementations for asynchronous interfaces.
*
* @class
* @summary
* type Interface = Promise | Node | Future
*/
var Interface = function () {
function Interface$2() {
}
function Promise$2() {
}
Promise$2.prototype = new Interface$2();
Promise$2.prototype.constructor = Promise$2;
function Node$2() {
}
Node$2.prototype = new Interface$2();
Node$2.prototype.constructor = Node$2;
function Future$2() {
}
Future$2.prototype = new Interface$2();
Future$2.prototype.constructor = Future$2;
var derived = adt.Base.derive({
name: 'Interface',
constructor: Interface$2,
prototype: Interface$2.prototype,
variants: [
{
name: 'Promise',
constructor: Promise$2,
prototype: Promise$2.prototype
},
{
name: 'Node',
constructor: Node$2,
prototype: Node$2.prototype
},
{
name: 'Future',
constructor: Future$2,
prototype: Future$2.prototype
}
]
});
Interface$2.Promise = new derived.variants[0].constructor();
Interface$2.Node = new derived.variants[1].constructor();
Interface$2.Future = new derived.variants[2].constructor();
return Interface$2;
}();
var Promise = Interface.Promise;
var Node = Interface.Node;
var Future = Interface.Future;
/**
* Constructs a DSL implementation for the given interface.
*
* @method
* @private
* @summary Interface → Specify.Core → DSL
*/
function makeDSL(asyncInterface, specify) {
var Hook = specify.Hook;
var TestSuite = specify.Test.Suite;
var TestCase = specify.Test.Case;
/**
* The DSL interface.
*
* @namespace DSL
*/
var DSL = {};
// -- Objects --------------------------------------------------------
/**
* Represents a test Suite.
*
* @memberof! DSL
* @class
* @summary
* type Suite <| Boo.Base {
* name :: String
* tests :: [Suite | Test]
* beforeEach :: [Future(Error, Void)]
* afterEeach :: [Future(Error, Void)]
* beforeAll :: [Future(Error, Void)]
* afterAll :: [Future(Error, Void)]
* }
*/
var Suite = Base.derive({
init: function _init(name) {
this.name = name;
this.tests = [];
this.beforeEach = [];
this.afterEach = [];
this.beforeAll = [];
this.afterAll = [];
},
construct: function () {
return TestSuite.create({
name: this.name,
tests: this.tests.map(function (a) {
return a.construct();
}),
beforeAll: Hook(this.beforeAll),
afterAll: Hook(this.afterAll),
beforeEach: Hook(this.beforeEach),
afterEach: Hook(this.afterEach)
});
}
});
/**
* Represents a test Case.
*
* @class
* @summary
* type Test <| Boo.Base {
* name :: String
* test :: Future(Error, Void)
* timeout :: Maybe(<Number/ms>)
* slow :: Maybe(<Number/ms>)
* enabled :: Maybe(Case → Boolean)
* }
*/
var Test = Base.derive({
init: function _init(name, test) {
this.name = name;
this.test = test;
this.slow = new Maybe.Nothing();
this.timeout = new Maybe.Nothing();
this.enabled = new Maybe.Nothing();
},
construct: function () {
return TestCase.create({
name: this.name,
test: this.test,
slow: this.slow,
timeout: this.timeout,
enabled: this.enabled
});
},
enable: function () {
return this.enableWhen(function (_) {
return true;
});
},
disable: function () {
return this.enableWhen(function (_) {
return false;
});
},
enableWhen: function (f) {
this.enabled = new Maybe.Just(f);
return this;
},
setSlow: function (a) {
this.slow = new Maybe.Just(a);
return this;
},
setTimeout: function (a) {
this.timeout = new Maybe.Just(a);
return this;
}
});
// -- Interface ------------------------------------------------------
spec = curry(3, spec);
function spec(parent, name, body) {
var suite = Suite.make(name);
body.call(makeContext(suite), it(suite), spec(suite));
parent.tests.push(suite);
return suite;
}
it = curry(3, it);
function it(parent, name, code) {
var action = new Future(function (reject, resolve) {
try {
resolve(code());
} catch (e) {
reject(e);
}
});
var test = Test.make(name, action);
parent.tests.push(test);
return test;
}
asyncFuture = curry(3, asyncFuture);
function asyncFuture(parent, name, code) {
var test = Test.make(name, code);
parent.tests.push(test);
return test;
}
asyncPromise = curry(3, asyncPromise);
function asyncPromise(parent, name, code) {
var test = Test.make(name, fromPromise(code()));
parent.tests.push(test);
return test;
}
asyncNode = curry(3, asyncNode);
function asyncNode(parent, name, code) {
var test = Test.make(name, liftNode(code)());
parent.tests.push(test);
return test;
}
beforeEach = curry(2, beforeEach);
function beforeEach(parent, code) {
parent.beforeEach.push(code);
}
afterEach = curry(2, afterEach);
function afterEach(parent, code) {
parent.afterEach.push(code);
}
beforeAll = curry(2, beforeAll);
function beforeAll(parent, code) {
parent.beforeAll.push(code);
}
afterAll = curry(2, afterAll);
function afterAll(parent, code) {
parent.afterAll.push(code);
}
function makeContext(parent) {
return {
it: it(parent),
spec: spec(parent),
async: selectAsync()(parent),
asyncPromise: asyncPromise(parent),
asyncNode: asyncNode(parent),
asyncFuture: asyncFuture(parent),
beforeEach: beforeEach(parent),
afterEach: afterEach(parent),
beforeAll: beforeAll(parent),
afterAll: afterAll(parent)
};
}
function selectAsync() {
return function (a0) {
if (Promise.hasInstance ? Promise.hasInstance(a0) : a0 instanceof Promise) {
return asyncPromise;
}
if (Node.hasInstance ? Node.hasInstance(a0) : a0 instanceof Node) {
return asyncNode;
}
if (Future.hasInstance ? Future.hasInstance(a0) : a0 instanceof Future) {
return asyncFuture;
}
throw new TypeError('No match');
}.call(this, asyncInterface);
}
return function (name, body) {
var root = Suite.make(name);
body.call(makeContext(root), it(root), spec(root));
return root.construct();
};
}
// -- Exports ----------------------------------------------------------
var dsl = module.exports = curry(2, makeDSL);
dsl.promise = dsl(Promise);
dsl.node = dsl(Node);
dsl.future = dsl(Future);
dsl.Interface = Interface;
//# sourceMappingURL=core.js.map